---
[](https://discord.gg/3XFf78nAx5)
-[](https://twitter.com/intent/follow?screen_name=codeiumdev)
-
-[](https://codeium.com?repo_name=exafunction%2Fcodeium.vim)
+[](https://twitter.com/intent/follow?screen_name=windsurf_ai)
+
+[](https://docs.windsurf.com)
+[](https://windsurf.canny.io/feature-requests/)
+[](https://windsurf.com?repo_name=exafunction%2Fwindsurf.vim)
[](https://marketplace.visualstudio.com/items?itemName=Codeium.codeium)
[](https://plugins.jetbrains.com/plugin/20540-codeium/)
[](https://open-vsx.org/extension/Codeium/codeium)
[](https://chrome.google.com/webstore/detail/codeium/hobjkcpmjhlegmobgonaagepfckjkceh)
-# codeium.vim
+# windsurf.vim
_Free, ultrafast Copilot alternative for Vim and Neovim_
-Codeium autocompletes your code with AI in all major IDEs. We [launched](https://www.codeium.com/blog/codeium-copilot-alternative-in-vim) this implementation of the Codeium plugin for Vim and Neovim to bring this modern coding superpower to more developers. Check out our [playground](https://www.codeium.com/playground) if you want to quickly try out Codeium online.
+Windsurf autocompletes your code with AI in all major IDEs. We [launched](https://www.windsurf.com/blog/codeium-copilot-alternative-in-vim) this implementation of the Windsurf plugin for Vim and Neovim to bring this modern coding superpower to more developers. Check out our [playground](https://www.windsurf.com/playground) if you want to quickly try out Windsurf online.
Contributions are welcome! Feel free to submit pull requests and issues related to the plugin.
@@ -33,13 +35,13 @@ Contributions are welcome! Feel free to submit pull requests and issues related
1. Install [Vim](https://github.com/vim/vim) (at least 9.0.0185) or [Neovim](https://github.com/neovim/neovim/releases/latest) (at
least 0.6)
-2. Install `Exafunction/codeium.vim` using your vim plugin manager of
+2. Install `Exafunction/windsurf.vim` using your vim plugin manager of
choice, or manually. See [Installation Options](#-installation-options) below.
-3. Run `:Codeium Auth` to set up the plugin and start using Codeium.
+3. Run `:Codeium Auth` to set up the plugin and start using Windsurf.
You can run `:help codeium` for a full list of commands and configuration
-options, or see [this guide](https://www.codeium.com/vim_tutorial) for a quick tutorial on how to use Codeium.
+options, or see [this guide](https://www.windsurf.com/vim_tutorial) for a quick tutorial on how to use Windsurf.
## 🛠️ Configuration
@@ -48,7 +50,7 @@ A few of the most popular options are highlighted below.
### ⌨️ Keybindings
-Codeium provides the following functions to control suggestions:
+Windsurf provides the following functions to control suggestions:
| Action | Function | Default Binding |
| --------------------------- | ------------------------------ | --------------- |
@@ -60,7 +62,7 @@ Codeium provides the following functions to control suggestions:
| Accept word from suggestion | `codeium#AcceptNextWord()` | `` |
| Accept line from suggestion | `codeium#AcceptNextLine()` | `` |
-Codeium's default keybindings can be disabled by setting
+Windsurf's default keybindings can be disabled by setting
```vim
let g:codeium_disable_bindings = 1
@@ -91,7 +93,7 @@ Or in Neovim (using [wbthomason/packer.nvim](https://github.com/wbthomason/packe
```lua
-- Remove the `use` here if you're using folke/lazy.nvim.
use {
- 'Exafunction/codeium.vim',
+ 'Exafunction/windsurf.vim',
config = function ()
-- Change '' here to any keycode you like.
vim.keymap.set('i', '', function () return vim.fn['codeium#Accept']() end, { expr = true, silent = true })
@@ -104,9 +106,9 @@ use {
(Make sure that you ran `:Codeium Auth` after installation.)
-### ⛔ Disabling Codeium
+### ⛔ Disabling Windsurf
-Codeium can be disabled for particular filetypes by setting the
+Windsurf can be disabled for particular filetypes by setting the
`g:codeium_filetypes` variable in your vim config file (vimrc/init.vim):
```vim
@@ -116,7 +118,7 @@ let g:codeium_filetypes = {
\ }
```
-Codeium is enabled by default for most filetypes.
+Windsurf is enabled by default for most filetypes.
You can also _disable_ codeium by default with the `g:codeium_enabled` variable,
and enable it manually per buffer by running `:CodeiumEnable`:
@@ -161,32 +163,32 @@ To disable automatic text rendering of suggestions (the gray text that appears f
let g:codeium_render = v:false
```
-### Show Codeium status in statusline
+### Show Windsurf status in statusline
-Codeium status can be generated by calling the `codeium#GetStatusString()` function. In
+Windsurf status can be generated by calling the `codeium#GetStatusString()` function. In
Neovim, you can use `vim.api.nvim_call_function("codeium#GetStatusString", {})` instead.
-It produces a 3 char long string with Codeium status:
+It produces a 3 char long string with Windsurf status:
- `'3/8'` - third suggestion out of 8
-- `'0'` - Codeium returned no suggestions
-- `'*'` - waiting for Codeium response
+- `'0'` - Windsurf returned no suggestions
+- `'*'` - waiting for Windsurf response
-In normal mode, status shows if Codeium is enabled or disabled by showing
+In normal mode, status shows if Windsurf is enabled or disabled by showing
`'ON'` or `'OFF'`.
In order to show it in status line add following line to your `.vimrc`:
```set statusline+=\{…\}%3{codeium#GetStatusString()}```
-Shorter variant without Codeium logo:
+Shorter variant without Windsurf logo:
```set statusline+=%3{codeium#GetStatusString()}```
Please check `:help statusline` for further information about building statusline in VIM.
-vim-airline supports Codeium out-of-the-box since commit [3854429d](https://github.com/vim-airline/vim-airline/commit/3854429d99c8a2fb555a9837b155f33c957a2202).
+vim-airline supports Windsurf out-of-the-box since commit [3854429d](https://github.com/vim-airline/vim-airline/commit/3854429d99c8a2fb555a9837b155f33c957a2202).
-### Launching Codeium Chat
+### Launching Windsurf Chat
Calling the `codeium#Chat()` function or using the `Codeium Chat` command will enable search and indexing in the current project and launch Codeium Chat in a new browser window.
@@ -207,7 +209,7 @@ Note that launching chat enables telemetry.
```lua
{
- 'Exafunction/codeium.vim',
+ 'Exafunction/windsurf.vim',
event = 'BufEnter'
}
```
@@ -215,19 +217,19 @@ Note that launching chat enables telemetry.
### 🔌 vim-plug
```vim
-Plug 'Exafunction/codeium.vim', { 'branch': 'main' }
+Plug 'Exafunction/windsurf.vim', { 'branch': 'main' }
```
### 📦 Vundle
```vim
-Plugin 'Exafunction/codeium.vim'
+Plugin 'Exafunction/windsurf.vim'
```
### 📦 packer.nvim:
```vim
-use 'Exafunction/codeium.vim'
+use 'Exafunction/windsurf.vim'
```
### 💪 Manual
@@ -238,7 +240,7 @@ Run the following. On windows, you can replace `~/.vim` with
`$HOME/vimfiles`:
```bash
-git clone https://github.com/Exafunction/codeium.vim ~/.vim/pack/Exafunction/start/codeium.vim
+git clone https://github.com/Exafunction/windsurf.vim ~/.vim/pack/Exafunction/start/windsurf.vim
```
#### 💻 Neovim
@@ -247,5 +249,5 @@ Run the following. On windows, you can replace `~/.config` with
`$HOME/AppData/Local`:
```bash
-git clone https://github.com/Exafunction/codeium.vim ~/.config/nvim/pack/Exafunction/start/codeium.vim
+git clone https://github.com/Exafunction/windsurf.vim ~/.config/nvim/pack/Exafunction/start/windsurf.vim
```
diff --git a/assets/codeium_logo.svg b/assets/codeium_logo.svg
deleted file mode 100644
index 7ca8b3e8..00000000
--- a/assets/codeium_logo.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-
diff --git a/assets/simple_logo.svg b/assets/simple_logo.svg
deleted file mode 100644
index 99f47640..00000000
--- a/assets/simple_logo.svg
+++ /dev/null
@@ -1,34 +0,0 @@
-
diff --git a/autoload/codeium.vim b/autoload/codeium.vim
index 0ea437e1..61789f38 100644
--- a/autoload/codeium.vim
+++ b/autoload/codeium.vim
@@ -419,12 +419,7 @@ function! codeium#CycleOrComplete() abort
endif
endfunction
-function! s:LaunchChat(out, err, status) abort
- let l:metadata = codeium#server#RequestMetadata()
- let l:processes = json_decode(join(a:out, ''))
- let l:chat_port = l:processes['chatClientPort']
- let l:ws_port = l:processes['chatWebServerPort']
-
+function BuildChatUrl(metadata, chat_port, ws_port) abort
let config = get(g:, 'codeium_server_config', {})
let l:has_enterprise_extension = 'false'
if has_key(config, 'api_url') && !empty(config.api_url)
@@ -432,7 +427,17 @@ function! s:LaunchChat(out, err, status) abort
endif
" Hard-coded to English locale and allowed telemetry.
- let l:url = 'http://127.0.0.1:' . l:chat_port . '/?' . 'api_key=' . l:metadata.api_key . '&ide_name=' . l:metadata.ide_name . '&ide_version=' . l:metadata.ide_version . '&extension_name=' . l:metadata.extension_name . '&extension_version=' . l:metadata.extension_version . '&web_server_url=ws://127.0.0.1:' . l:ws_port . '&has_enterprise_extension=' . l:has_enterprise_extension . '&app_name=Vim&locale=en&ide_telemetry_enabled=true&has_index_service=true'
+ let l:url = 'http://127.0.0.1:' . a:chat_port . '/?' . 'api_key=' . a:metadata.api_key . '&ide_name=' . a:metadata.ide_name . '&ide_version=' . a:metadata.ide_version . '&extension_name=' . a:metadata.extension_name . '&extension_version=' . a:metadata.extension_version . '&web_server_url=ws://127.0.0.1:' . a:ws_port . '&has_enterprise_extension=' . l:has_enterprise_extension . '&app_name=Vim&locale=en&ide_telemetry_enabled=true&has_index_service=true'
+ return l:url
+endfunction
+
+function! s:LaunchChat(out, err, status) abort
+ let l:metadata = codeium#server#RequestMetadata()
+ let l:processes = json_decode(join(a:out, ''))
+ let l:chat_port = l:processes['chatClientPort']
+ let l:ws_port = l:processes['chatWebServerPort']
+
+ let l:url = BuildChatUrl(l:metadata, l:chat_port, l:ws_port)
let l:browser = codeium#command#BrowserCommand()
let opened_browser = v:false
if !empty(browser)
@@ -473,7 +478,7 @@ endfunction
function! codeium#RefreshContext() abort
" current buffer is 1
try
- call codeium#server#Request('RefreshContextForIdeAction', {'active_document': codeium#doc#GetDocument(1, line('.'), line('.'))})
+ call codeium#server#Request('RefreshContextForIdeAction', {'active_document': codeium#doc#GetDocument(1, line('.'), col('.'))})
catch
call codeium#log#Exception()
endtry
@@ -501,6 +506,14 @@ function! codeium#Chat() abort
call codeium#RefreshContext()
call codeium#server#Request('GetProcesses', codeium#server#RequestMetadata(), function('s:LaunchChat', []))
call codeium#AddTrackedWorkspace()
+ " If user has chat_ports set, they are probably using vim remotely and trying to use chat via port forwarding.
+ " In that case display the url here so that it is easier to copy, as the browser will fail to open automatically.
+ let chat_ports = get(g:, 'codeium_port_config', {})
+ if has_key(chat_ports, 'chat_client') && !empty(chat_ports.chat_client) && has_key(chat_ports, 'web_server') && !empty(chat_ports.web_server)
+ let l:metadata = codeium#server#RequestMetadata()
+ let l:url = BuildChatUrl(l:metadata, chat_ports.chat_client, chat_ports.web_server)
+ echomsg l:url
+ endif
catch
call codeium#log#Exception()
endtry
diff --git a/autoload/codeium/command.vim b/autoload/codeium/command.vim
index 9a90173c..e7350287 100644
--- a/autoload/codeium/command.vim
+++ b/autoload/codeium/command.vim
@@ -91,7 +91,7 @@ function! s:commands.Auth(...) abort
endif
while empty(api_key) && tries < 3
- let command = 'curl -sS ' . register_user_url . ' ' .
+ let command = 'curl -sSL ' . register_user_url . ' ' .
\ '--header "Content-Type: application/json" ' .
\ '--data ' . shellescape(json_encode({'firebase_id_token': auth_token}))
let response = system(command)
@@ -104,7 +104,7 @@ function! s:commands.Auth(...) abort
\ . 'Would you like to try auth without checking SSL certificate revocation? (y/n): ')
call inputrestore()
if useNoSsl ==? 'y'
- let command = 'curl --ssl-no-revoke -sS ' . register_user_url . ' ' .
+ let command = 'curl --ssl-no-revoke -sSL ' . register_user_url . ' ' .
\ '--header "Content-Type: application/json" ' .
\ '--data ' . shellescape(json_encode({'firebase_id_token': auth_token}))
let response = system(command)
diff --git a/autoload/codeium/server.vim b/autoload/codeium/server.vim
index ff9c1c49..eba00cf5 100644
--- a/autoload/codeium/server.vim
+++ b/autoload/codeium/server.vim
@@ -25,8 +25,91 @@ if !exists('s:editor_version')
endif
let s:server_port = v:null
+if codeium#util#IsUsingRemoteChat()
+ let s:server_port = 42100
+endif
+
let g:codeium_server_job = v:null
+function! s:DetectGlibcVersion() abort
+ if !has('unix') || has('mac')
+ return v:null
+ endif
+
+ try
+ try
+ let ldd_output = system('ldd --version 2>/dev/null')
+ if v:shell_error == 0
+ let match = matchlist(ldd_output, 'ldd (GNU libc) \(\d\+\.\d\+\)')
+ if !empty(match)
+ call codeium#log#Info('Detected glibc version via ldd: ' . match[1])
+ return match[1]
+ endif
+ endif
+ catch
+ endtry
+
+ try
+ let getconf_output = system('getconf GNU_LIBC_VERSION 2>/dev/null')
+ if v:shell_error == 0
+ let match = matchlist(getconf_output, 'glibc \(\d\+\.\d\+\)')
+ if !empty(match)
+ call codeium#log#Info('Detected glibc version via getconf: ' . match[1])
+ return match[1]
+ endif
+ endif
+ catch
+ endtry
+
+ try
+ let libc_output = system('/lib/x86_64-linux-gnu/libc.so.6 2>/dev/null')
+ if v:shell_error == 0
+ let match = matchlist(libc_output, 'GNU C Library.*release version \(\d\+\.\d\+\)')
+ if !empty(match)
+ call codeium#log#Info('Detected glibc version via libc.so.6: ' . match[1])
+ return match[1]
+ endif
+ endif
+ catch
+ endtry
+
+ call codeium#log#Warn('Could not detect glibc version using any method')
+ return v:null
+ catch
+ call codeium#log#Error('Error detecting glibc version: ' . v:exception)
+ return v:null
+ endtry
+endfunction
+
+function! s:CompareVersions(version1, version2) abort
+ let parts1 = split(a:version1, '\.')
+ let parts2 = split(a:version2, '\.')
+
+ let major1 = str2nr(parts1[0])
+ let minor1 = str2nr(parts1[1])
+ let major2 = str2nr(parts2[0])
+ let minor2 = str2nr(parts2[1])
+
+ if major1 != major2
+ return major1 < major2 ? -1 : 1
+ endif
+
+ if minor1 != minor2
+ return minor1 < minor2 ? -1 : 1
+ endif
+
+ return 0
+endfunction
+
+function! s:IsGlibcVersionLessOrEqual(target_version) abort
+ let current_version = s:DetectGlibcVersion()
+ if current_version is# v:null
+ return v:false
+ endif
+
+ return s:CompareVersions(current_version, a:target_version) <= 0
+endfunction
+
function! s:OnExit(result, status, on_complete_cb) abort
let did_close = has_key(a:result, 'closed')
if did_close
@@ -69,7 +152,7 @@ function! codeium#server#Request(type, data, ...) abort
\ '/exa.language_server_pb.LanguageServerService/' . a:type
let data = json_encode(a:data)
let args = [
- \ 'curl', uri,
+ \ 'curl', '-L', uri,
\ '--header', 'Content-Type: application/json',
\ '-d@-'
\ ]
@@ -184,13 +267,24 @@ function! codeium#server#Start(...) abort
let config = get(g:, 'codeium_server_config', {})
if has_key(config, 'portal_url') && !empty(config.portal_url)
- let response = system('curl -s ' . config.portal_url . '/api/version')
- if v:shell_error == '0'
- let s:language_server_version = response
+ let has_old_glibc = s:IsGlibcVersionLessOrEqual('2.27')
+ if has_old_glibc
+ call codeium#log#Info('Using legacy language server version 1.46.0 for enterprise customer with glibc <= 2.27')
+ let s:language_server_version = '1.46.0'
+ let s:language_server_sha = 'enterprise-' . s:language_server_version
+ elseif config.portal_url =~# '\.windsurf\.com' || config.portal_url =~# 'dstart\.com'
+ call codeium#log#Info('Using pinned language server version 1.50.100 for enterprise customer')
+ let s:language_server_version = '1.50.100'
let s:language_server_sha = 'enterprise-' . s:language_server_version
else
- call codeium#log#Error('Failed to fetch version from ' . config.portal_url)
- call codeium#log#Error(v:shell_error)
+ let response = system('curl -sL ' . config.portal_url . '/api/version')
+ if v:shell_error == '0'
+ let s:language_server_version = response
+ let s:language_server_sha = 'enterprise-' . s:language_server_version
+ else
+ call codeium#log#Error('Failed to fetch version from ' . config.portal_url)
+ call codeium#log#Error(v:shell_error)
+ endif
endif
endif
@@ -235,7 +329,8 @@ function! s:UnzipAndStart(status) abort
let old_shellredir = &shellredir
" Switch to powershell.
let &shell = 'powershell'
- set shellquote= shellpipe=\| shellxquote=
+ set shellquote=\"
+ set shellpipe=\|
set shellcmdflag=-NoLogo\ -NoProfile\ -ExecutionPolicy\ RemoteSigned\ -Command
set shellredir=\|\ Out-File\ -Encoding\ UTF8
call system('& { . ' . shellescape(s:root . '/powershell/gzip.ps1') . '; Expand-File ' . shellescape(s:bin . '.gz') . ' }')
@@ -266,11 +361,9 @@ function! s:ActuallyStart() abort
let chat_ports = get(g:, 'codeium_port_config', {})
let manager_dir = tempname() . '/codeium/manager'
call mkdir(manager_dir, 'p')
-
let args = [
\ s:bin,
\ '--api_server_url', get(config, 'api_url', 'https://server.codeium.com'),
- \ '--manager_dir', manager_dir,
\ '--enable_local_search', '--enable_index_service', '--search_max_workspace_file_count', '5000',
\ '--enable_chat_web_server', '--enable_chat_client'
\ ]
@@ -278,6 +371,9 @@ function! s:ActuallyStart() abort
let args += ['--enterprise_mode']
let args += ['--portal_url', get(config, 'portal_url', 'https://codeium.example.com')]
endif
+ if !codeium#util#IsUsingRemoteChat()
+ let args += ['--manager_dir', manager_dir]
+ endif
" If either of these is set, only one vim window (with any number of buffers) will work with Codeium.
" Opening other vim windows won't be able to use Codeium features.
if has_key(chat_ports, 'web_server') && !empty(chat_ports.web_server)
@@ -298,6 +394,9 @@ function! s:ActuallyStart() abort
\ 'err_cb': { channel, data -> codeium#log#Info('[SERVER] ' . data) },
\ })
endif
- call timer_start(500, function('s:FindPort', [manager_dir]), {'repeat': -1})
+ if !codeium#util#IsUsingRemoteChat()
+ call timer_start(500, function('s:FindPort', [manager_dir]), {'repeat': -1})
+ endif
+
call timer_start(5000, function('s:SendHeartbeat', []), {'repeat': -1})
endfunction
diff --git a/autoload/codeium/util.vim b/autoload/codeium/util.vim
index 3d91a446..48eae30b 100644
--- a/autoload/codeium/util.vim
+++ b/autoload/codeium/util.vim
@@ -8,3 +8,8 @@ function! codeium#util#HasSupportedVersion() abort
return s:nvim_virt_text_support || s:vim_virt_text_support
endfunction
+
+function! codeium#util#IsUsingRemoteChat() abort
+ let chat_ports = get(g:, 'codeium_port_config', {})
+ return has_key(chat_ports, 'chat_client') && !empty(chat_ports.chat_client) && has_key(chat_ports, 'web_server') && !empty(chat_ports.web_server)
+endfunction
diff --git a/codeium.svg b/codeium.svg
deleted file mode 100644
index 7df5eb2d..00000000
--- a/codeium.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/doc/codeium.txt b/doc/codeium.txt
index 4a30ebfd..5c33c70d 100644
--- a/doc/codeium.txt
+++ b/doc/codeium.txt
@@ -115,8 +115,12 @@ g:codeium_arch Manually set the host architecture, accepted values
g:codeium_port_config
Set the ports the chat client and web server use.
Pass in web_server and chat_client fields to the mapping to set.
- Please note that if either of the ports are specified, only one
+ Please note that if this option is set, only one
window will work with codeium.
+ It is recommended to set both the web_server and chat_client options
+ if using this.
+ If you are setting this because you are using vim remotely and want chat to work
+ you will need to forward the two ports you set here, along with port 42100.
That window can have as many buffers within it, but any other
opened windows will not be able to use Codeium's features.
>
diff --git a/windsurf.png b/windsurf.png
new file mode 100644
index 00000000..cd191d57
Binary files /dev/null and b/windsurf.png differ