Skip to content

Commit 82332cf

Browse files
committed
refactor(provider)!: replace providers with simpler, more maintainable server option
The plugin's purpose is _interfacing_ with `opencode` - running it is just a neat convenience. But as the plugin has grown (yay!), that "neat convenience" has become endless quirks and the majority of maintenance work. Unfortunately, I'm forced to make the difficult call to remove providers to make time for more useful work. I retained the embedded terminal (and instructions to integrate e.g. `snacks.terminal`) because it's useful to have _some_ way to get started. But beyond that, it's not practical to service every user's preferences. And anyway, it's bad UX to ask them to understand a new way of using/configuring their terminal environment. It may make sense as its own plugin (and feel free to extract the code for that!), but as far as `opencode.nvim` goes, it is far, far out of scope. Thank you for understanding! I look forward to bringing you more cool features :D #118 #180 #166 #104 #150 #119 #105
1 parent 6d00f30 commit 82332cf

17 files changed

Lines changed: 311 additions & 1141 deletions

README.md

Lines changed: 37 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Integrate the [opencode](https://github.com/sst/opencode) AI assistant with Neov
4444
},
4545
},
4646
},
47-
terminal = {}, -- Enables the `snacks` provider
4847
},
4948
},
5049
},
@@ -123,155 +122,60 @@ Select or reference prompts to review, explain, and improve your code:
123122
| `review` | Review `@this` for correctness and readability |
124123
| `test` | Add tests for `@this` |
125124

126-
### Provider
125+
### Server
127126

128-
You can manually run `opencode` however you like and `opencode.nvim` will find them!
129-
130-
If `opencode.nvim` can't find an existing `opencode`, it uses the configured provider (defaulting based on availability) to manage one for you.
127+
You can manually run `opencode`s however you like and `opencode.nvim` will find them!
131128

132129
> [!IMPORTANT]
133-
> You _must_ run `opencode` with the `--port` flag to expose its server. Providers do so by default.
134-
135-
<details>
136-
<summary><a href="https://neovim.io/doc/user/terminal.html">Neovim terminal</a></summary>
137-
138-
```lua
139-
vim.g.opencode_opts = {
140-
provider = {
141-
enabled = "terminal",
142-
terminal = {
143-
-- ...
144-
}
145-
}
146-
}
147-
```
148-
149-
</details>
150-
151-
<details>
152-
<summary><a href="https://github.com/folke/snacks.nvim/blob/main/docs/terminal.md">snacks.terminal</a></summary>
153-
154-
```lua
155-
vim.g.opencode_opts = {
156-
provider = {
157-
enabled = "snacks",
158-
snacks = {
159-
-- ...
160-
}
161-
}
162-
}
163-
```
164-
165-
</details>
130+
> You _must_ run `opencode` with the `--port` flag to expose its server.
166131
167-
<details>
168-
<summary><a href="https://sw.kovidgoyal.net/kitty/">kitty</a></summary>
132+
If `opencode.nvim` can't find an existing `opencode`, it uses the configured server to start one for you, defaulting to an embedded terminal.
169133

170-
```lua
171-
vim.g.opencode_opts = {
172-
provider = {
173-
enabled = "kitty",
174-
kitty = {
175-
-- ...
176-
}
177-
}
178-
}
179-
```
180-
181-
The kitty provider requires [remote control via a socket](https://sw.kovidgoyal.net/kitty/remote-control/#remote-control-via-a-socket) to be enabled.
182-
183-
You can do this either by running Kitty with the following command:
184-
185-
```bash
186-
# For Linux only:
187-
kitty -o allow_remote_control=yes --single-instance --listen-on unix:@mykitty
188-
189-
# Other UNIX systems:
190-
kitty -o allow_remote_control=yes --single-instance --listen-on unix:/tmp/mykitty
191-
```
192-
193-
OR, by adding the following to your `kitty.conf`:
194-
195-
```
196-
# For Linux only:
197-
allow_remote_control yes
198-
listen_on unix:@mykitty
199-
# Other UNIX systems:
200-
allow_remote_control yes
201-
listen_on unix:/tmp/kitty
202-
```
203-
204-
</details>
134+
#### Keymaps
205135

206-
<details>
207-
<summary><a href="https://wezterm.org/">wezterm</a></summary>
136+
`opencode.nvim` sets these normal-mode keymaps in the embedded terminal for Neovim-like message navigation:
208137

209-
```lua
210-
vim.g.opencode_opts = {
211-
provider = {
212-
enabled = "wezterm",
213-
wezterm = {
214-
-- ...
215-
}
216-
}
217-
}
218-
```
138+
| Keymap | Command | Description |
139+
| ------- | ------------------------ | --------------------- |
140+
| `<C-u>` | `session.half.page.up` | Scroll up half page |
141+
| `<C-d>` | `session.half.page.down` | Scroll down half page |
142+
| `gg` | `session.first` | Go to first message |
143+
| `G` | `session.last` | Go to last message |
144+
| `<Esc>` | `session.interrupt` | Interrupt |
219145

220-
</details>
146+
#### Customization
221147

222-
<details>
223-
<summary><a href="https://github.com/tmux/tmux">tmux</a></summary>
148+
Example using [`snacks.terminal`](https://github.com/folke/snacks.nvim/blob/main/docs/terminal.md) instead:
224149

225150
```lua
226-
vim.g.opencode_opts = {
227-
provider = {
228-
enabled = "tmux",
229-
tmux = {
230-
-- ...
231-
}
232-
}
151+
local opencode_cmd = 'opencode --port'
152+
---@type snacks.terminal.Opts
153+
local snacks_terminal_opts = {
154+
win = {
155+
position = 'right',
156+
enter = false,
157+
on_win = function(win)
158+
-- Set up keymaps and cleanup for an arbitrary terminal
159+
require('opencode.terminal').setup(win.win)
160+
end,
161+
},
233162
}
234-
```
235-
236-
</details>
237-
238-
<details>
239-
<summary>custom</summary>
240-
241-
Integrate your custom method for convenience!
242-
243-
```lua
163+
---@type opencode.Opts
244164
vim.g.opencode_opts = {
245-
provider = {
246-
toggle = function(self)
247-
-- ...
165+
server = {
166+
start = function()
167+
require('snacks.terminal').open(opencode_cmd, snacks_terminal_opts)
248168
end,
249-
start = function(self)
250-
-- ...
169+
stop = function()
170+
require('snacks.terminal').get(opencode_cmd, snacks_terminal_opts):close()
251171
end,
252-
stop = function(self)
253-
-- ...
172+
toggle = function()
173+
require('snacks.terminal').toggle(opencode_cmd, snacks_terminal_opts)
254174
end,
255-
}
175+
},
256176
}
257177
```
258178

259-
</details>
260-
261-
Please submit PRs adding new providers! 🙂
262-
263-
#### Keymaps
264-
265-
`opencode.nvim` sets these buffer-local keymaps in provider terminals for Neovim-like message navigation:
266-
267-
| Keymap | Command | Description |
268-
| ------- | ------------------------ | --------------------- |
269-
| `<C-u>` | `session.half.page.up` | Scroll up half page |
270-
| `<C-d>` | `session.half.page.down` | Scroll down half page |
271-
| `<Esc>` | `session.interrupt` | Interrupt |
272-
| `gg` | `session.first` | Go to first message |
273-
| `G` | `session.last` | Go to last message |
274-
275179
## 🚀 Usage
276180

277181
### Ask — `require("opencode").ask()`
@@ -293,7 +197,7 @@ Select from all `opencode.nvim` functionality.
293197
- Prompts
294198
- Commands
295199
- Fetches custom commands from `opencode`
296-
- Provider controls
200+
- Server controls
297201

298202
Highlights and previews items when using `snacks.picker`.
299203

@@ -343,7 +247,7 @@ Command `opencode`:
343247
| LSP Function | `opencode.nvim` Handler |
344248
| ------------ | ----------------------------------------------------------------------- |
345249
| Hover | Asks `opencode` for a brief explanation of the symbol under the cursor. |
346-
| Code Actions | Asks `opencode` to explain or fix diagnostics under the cursor. |
250+
| Code Actions | Asks `opencode` to explain or fix diagnostics under the cursor. |
347251

348252
## 👀 Events
349253

lua/opencode.lua

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ end
4949
--- - Prompts
5050
--- - Commands
5151
--- - Fetches custom commands from `opencode`
52-
--- - Provider controls
5352
--- - Server controls
5453
---
5554
--- Highlights and previews items when using `snacks.picker`.
@@ -131,12 +130,36 @@ end
131130
M.operator = require("opencode.api.operator").operator
132131

133132
----------------
134-
--- Provider ---
133+
--- Server ---
135134
----------------
136135

137-
M.toggle = require("opencode.provider").toggle
138-
M.start = require("opencode.provider").start
139-
M.stop = require("opencode.provider").stop
136+
---Toggle the configured `opencode` server.
137+
M.toggle = function()
138+
local opts = require("opencode.config").opts
139+
if opts.server and opts.server.toggle then
140+
opts.server.toggle()
141+
else
142+
vim.notify("No server `toggle` function configured", vim.log.levels.ERROR, { title = "opencode" })
143+
end
144+
end
145+
---Start the configured `opencode` server.
146+
M.start = function()
147+
local opts = require("opencode.config").opts
148+
if opts.server and opts.server.start then
149+
opts.server.start()
150+
else
151+
vim.notify("No server `start` function configured", vim.log.levels.ERROR, { title = "opencode" })
152+
end
153+
end
154+
---Stop the configured `opencode` server.
155+
M.stop = function()
156+
local opts = require("opencode.config").opts
157+
if opts.server and opts.server.stop then
158+
opts.server.stop()
159+
else
160+
vim.notify("No server `stop` function configured", vim.log.levels.ERROR, { title = "opencode" })
161+
end
162+
end
140163

141164
--------------------
142165
--- Integrations ---

lua/opencode/cli/client.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ end
277277
---@field properties table
278278

279279
---Calls the `/event` SSE endpoint and invokes `callback` for each event received.
280-
---Stops any previous subscription, so only one is active at a time.
281280
---
282281
---@param port number
283282
---@param callback fun(response: opencode.cli.client.Event)|nil

lua/opencode/cli/server.lua

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
local M = {}
22

3+
---@class opencode.cli.server.Opts
4+
---
5+
---The port to look for `opencode` on.
6+
---When set, _only_ this port will be checked.
7+
---When not set, _all_ `opencode` processes will be checked.
8+
---Be sure to also launch `opencode` accordingly, e.g. `opencode --port 12345`.
9+
---@field port? number
10+
---
11+
---Start an `opencode` server.
12+
---Called when when none are found; will retry after.
13+
---@field start? fun()|false
14+
---
15+
---@field stop? fun()|false
16+
---
17+
---@field toggle? fun()|false
18+
319
---An `opencode` server process and some details about it.
420
---@class opencode.cli.server.Server
521
---@field port number
@@ -176,7 +192,7 @@ end
176192
---1. The currently subscribed server in `opencode.events`.
177193
---2. The configured port in `require("opencode.config").opts.port`.
178194
---3. All servers, prioritizing one sharing CWD with Neovim, and prompting the user to select if multiple are found.
179-
---4. Calling `require("opencode.provider").start()` to launch a new server, then retrying the above.
195+
---4. Calling `opts.server.start()`, then retrying the above.
180196
---
181197
---Upon success, subscribes to the server's events.
182198
---
@@ -185,10 +201,11 @@ end
185201
function M.get(launch)
186202
launch = launch ~= false
187203

204+
local opts = require("opencode.config").opts.server or {}
205+
188206
local Promise = require("opencode.promise")
189207
return Promise.resolve(
190-
require("opencode.events").connected_server and require("opencode.events").connected_server.port
191-
or require("opencode.config").opts.port
208+
require("opencode.events").connected_server and require("opencode.events").connected_server.port or opts.port
192209
)
193210
:next(function(priority_port) ---@param priority_port number
194211
if priority_port then
@@ -229,13 +246,13 @@ function M.get(launch)
229246
end
230247

231248
return Promise.new(function(resolve, reject)
232-
if launch then
233-
local start_ok, start_result = pcall(require("opencode.provider").start)
249+
if launch and opts.start then
250+
local start_ok, start_result = pcall(opts.start)
234251
if not start_ok then
235252
return reject("Error starting `opencode`: " .. start_result)
236253
end
237254

238-
-- Wait for the provider to start
255+
-- Wait for the server to start
239256
vim.defer_fn(function()
240257
resolve(true)
241258
end, 2000)

0 commit comments

Comments
 (0)