Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@jinzhongjia
Copy link
Contributor

@jinzhongjia jinzhongjia commented Jan 2, 2026

Title

feat(server): share opencode server process across multiple Neovim instances


Summary

This PR implements a shared server mechanism that allows multiple Neovim instances to share a single opencode serve process, reducing resource usage and improving startup time for subsequent instances.

Problem

Previously, each Neovim instance spawned its own opencode serve process. When working with multiple projects simultaneously, this resulted in:

  • Multiple redundant server processes consuming system resources
  • Slower startup time for each new instance
  • No coordination between instances

Solution

Implement a lock file mechanism at ~/.cache/nvim/opencode-server.lock that tracks:

  • Server URL
  • Owner PID (the instance that spawned the server)
  • Client PIDs (all instances using the server)

Key features:

  • Automatic server discovery: New instances check for an existing healthy server before spawning
  • Graceful cleanup: Server only terminates when the last client disconnects
  • Race condition prevention: File locking mechanism prevents concurrent access issues
  • Health checks: Validates existing server is responsive before reusing

Lock File Format

url=http://localhost:4096
clients=12345,67890,11111

Testing

  • All existing tests pass
  • New unit tests for lock file operations (14 tests)
  • Manual testing with multiple Neovim instances

Add a lock file mechanism to coordinate a single server process among
multiple Neovim clients. Track ownership and active clients in
opencode-server.lock to ensure the process persists until the last
instance closes. Additionally, implement URI encoding for API queries.
@jinzhongjia jinzhongjia marked this pull request as ready for review January 2, 2026 11:54
@jinzhongjia
Copy link
Contributor Author

jinzhongjia commented Jan 2, 2026

This PR is generated by AI with opencode and oh my opencode, but I have reviewed this code carefully.

I think this code is ok

Add logic to tests/unit/util_spec.lua to handle year transitions in
date formatting. The assertions now check the year of the timestamp
to determine if the year should be present in the output string.
@jinzhongjia jinzhongjia marked this pull request as draft January 2, 2026 12:11
Replace the `owner` field in the lock file with `server_pid` to
explicitly track the background process. Update `unregister_client`
to return this PID and remove client promotion logic.
nvim returns non-zero exit codes when error messages are printed,
even for expected errors in error handling tests. Changed test runner
to check for actual '[31mFail.*||' patterns in output instead.
@jinzhongjia jinzhongjia force-pushed the feat/single-opencode-client branch from 568d1a6 to f948664 Compare January 2, 2026 12:37
@jinzhongjia jinzhongjia marked this pull request as ready for review January 2, 2026 12:49
@sudo-tee
Copy link
Owner

sudo-tee commented Jan 5, 2026

Thanks for the PR this looks interesting, I will play with it a little bit

@jinzhongjia
Copy link
Contributor Author

If you need to modify code, feel free to contact me!

@jinzhongjia
Copy link
Contributor Author

This repository is great

Copy link
Owner

@sudo-tee sudo-tee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really great feature for the plugin, and it looks stable from the tests I did.

I did add some little nitpicking , but otherwise this looks good

local result_received = false
local is_healthy = false

curl.request({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cleaner to use the api-client.lua and add this route to it.

The api-client is already creating promises for the curl calls, so you can avoid using the vim.wait there

server.url = url
server.is_owner = false
register_client()
server.spawn_promise:resolve(server --[[@as any]])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should cast it to OpencodeServer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants