Skip to content

tachyons/gitlab-lsp.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

gitlab-lsp.nvim

A Neovim plugin that integrates GitLab LSP with OAuth device flow authentication for seamless GitLab Duo code suggestions.

✨ Features

  • 🔐 OAuth Device Flow Authentication - Secure authentication without exposing tokens
  • 🔄 Automatic Token Refresh - Handles token expiration transparently
  • 🚀 GitLab Duo Code Suggestions - AI-powered code completions
  • 🎯 Multi-language Support - Works with Ruby, Go, JavaScript, TypeScript, Rust, Lua, Python, and more
  • 💾 Token Persistence - Authenticate once, works across sessions
  • 🛠️ Easy Configuration - Works out of the box with sensible defaults
  • 🔌 Completion Engine Integration - Works seamlessly with nvim-cmp, blink.cmp, and native LSP completion

📋 Requirements

  • Neovim 0.11.0 or later (uses the new vim.lsp.config API)
  • plenary.nvim
  • Node.js and npm/npx (for running @gitlab-org/gitlab-lsp)
  • GitLab account with Duo Pro/Enterprise license

📦 Installation

Using lazy.nvim

return {
  'https://gitlab.com/tachyons-gitlab/gitlab-lsp',
  dependencies = { 'nvim-lua/plenary.nvim' },
  config = function()
    require('gitlab-lsp').setup({
      -- Optional: override default settings
      gitlab_url = 'https://gitlab.com', -- or your self-hosted instance
      filetypes = { 'ruby', 'go', 'javascript', 'typescript', 'rust', 'lua', 'python' },
      log_level = 'info', -- 'debug', 'info', 'warn', 'error'
    })
  end
}

Alternative shorter format:

{
  'gitlab.com/tachyons-gitlab/gitlab-lsp',
  dependencies = { 'nvim-lua/plenary.nvim' },
  config = function()
    require('gitlab-lsp').setup()
  end
}
use {
  'https://gitlab.com/tachyons-gitlab/gitlab-lsp',
  requires = { 'nvim-lua/plenary.nvim' },
  config = function()
    require('gitlab-lsp').setup()
  end
}

Manual Installation

# Clone the repository
git clone https://gitlab.com/tachyons-gitlab/gitlab-lsp.git \
  ~/.local/share/nvim/site/pack/plugins/start/gitlab-lsp

# Install plenary.nvim if not already installed
git clone https://github.com/nvim-lua/plenary.nvim.git \
  ~/.local/share/nvim/site/pack/plugins/start/plenary.nvim

Then add to your init.lua:

require('gitlab-lsp').setup()

🚀 Quick Start

  1. Install the plugin using your preferred method above

  2. Authenticate with GitLab:

    :GitLabAuth
  3. Follow the prompts:

    • Open the URL shown in your browser
    • Enter the device code
    • Authorize the application
  4. Start coding! The LSP will automatically start and provide code suggestions

💡 Completion Engine Integration

Using with blink.cmp

blink.cmp works automatically with GitLab LSP. Simply install both:

return {
  {
    'https://gitlab.com/tachyons-gitlab/gitlab-lsp',
    dependencies = { 'nvim-lua/plenary.nvim' },
    config = function()
      require('gitlab-lsp').setup()
    end
  },
  {
    'saghen/blink.cmp',
    dependencies = 'rafamadriz/friendly-snippets',
    version = 'v0.*',
    opts = {
      keymap = { preset = 'default' },
      appearance = {
        use_nvim_cmp_as_default = true,
        nerd_font_variant = 'mono'
      },
      sources = {
        default = { 'lsp', 'path', 'snippets', 'buffer' },
      },
    },
  }
}

Using with nvim-cmp

return {
  {
    'https://gitlab.com/tachyons-gitlab/gitlab-lsp',
    dependencies = { 'nvim-lua/plenary.nvim' },
    config = function()
      require('gitlab-lsp').setup()
    end
  },
  {
    'hrsh7th/nvim-cmp',
    dependencies = {
      'hrsh7th/cmp-nvim-lsp',
      'hrsh7th/cmp-buffer',
      'hrsh7th/cmp-path',
    },
    config = function()
      local cmp = require('cmp')
      cmp.setup({
        sources = cmp.config.sources({
          { name = 'nvim_lsp' },
          { name = 'buffer' },
          { name = 'path' },
        }),
        mapping = cmp.mapping.preset.insert({
          ['<C-Space>'] = cmp.mapping.complete(),
          ['<CR>'] = cmp.mapping.confirm({ select = true }),
        }),
      })
    end
  }
}

Using Native LSP Completion

GitLab LSP works with Neovim's built-in completion. Enable it with:

-- In your init.lua
vim.opt.completeopt = {'menu', 'menuone', 'noselect'}

-- Trigger completion manually with <C-x><C-o> in insert mode
-- Or set up automatic completion
vim.api.nvim_create_autocmd('TextChangedI', {
  pattern = '*',
  callback = function()
    if vim.fn.pumvisible() == 0 then
      vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<C-x><C-o>', true, true, true), 'n')
    end
  end
})

⚙️ Configuration

Default Configuration

require('gitlab-lsp').setup({
  -- GitLab instance URL
  gitlab_url = "https://gitlab.com",
  
  -- OAuth client ID (default is provided, but you can use your own)
  client_id = "5f1f9933c9bff0a3e908007703f260bf1ff87bcdb91d38279a9f0d0ddecceadf",
  
  -- OAuth scopes
  scopes = "api",
  
  -- Token storage location
  token_file = vim.fn.stdpath('data') .. '/gitlab_oauth_token.json',
  
  -- Supported file types
  filetypes = { "ruby", "go", "javascript", "typescript", "rust", "lua", "python" },
  
  -- Feature flags
  stream_code_generations = false,
  enable_secret_redaction = true,
  
  -- Log level: 'debug', 'info', 'warn', 'error'
  log_level = "info",
})

Self-Hosted GitLab

For self-hosted GitLab instances:

require('gitlab-lsp').setup({
  gitlab_url = 'https://gitlab.yourcompany.com',
  client_id = 'your_oauth_app_client_id', -- Create in your GitLab instance
})

Custom OAuth Application

To use your own OAuth application:

  1. Go to GitLab → Preferences → Applications
  2. Create a new application:
    • Name: Neovim GitLab LSP
    • Redirect URI: http://localhost (not used for device flow)
    • Scopes: Select api
    • Confidential: No (for device flow)
  3. Copy the Application ID
  4. Configure the plugin:
require('gitlab-lsp').setup({
  client_id = 'your_application_id_here',
})

📝 Commands

Command Description
:GitLabAuth Start OAuth device flow authentication
:GitLabTokenInfo Display token status and expiration time
:GitLabRefreshToken Manually refresh the access token
:GitLabStart Manually start the LSP server
:GitLabLogout Remove stored token and stop LSP

⌨️ Recommended Keybindings

Add to your init.lua:

vim.keymap.set('n', '<leader>ga', ':GitLabAuth<CR>', { desc = 'GitLab Auth' })
vim.keymap.set('n', '<leader>gi', ':GitLabTokenInfo<CR>', { desc = 'GitLab Token Info' })
vim.keymap.set('n', '<leader>gr', ':GitLabRefreshToken<CR>', { desc = 'GitLab Refresh Token' })
vim.keymap.set('n', '<leader>go', ':GitLabLogout<CR>', { desc = 'GitLab Logout' })

🔧 How It Works

  1. Device Flow Authentication:

    • User runs :GitLabAuth
    • Plugin requests a device code from GitLab
    • User opens the verification URL and enters the code
    • Plugin polls GitLab until authorization is complete
    • Access token and refresh token are saved locally
  2. Token Management:

    • Tokens are stored in ~/.local/share/nvim/gitlab_oauth_token.json
    • Access tokens are valid for 2 hours
    • Plugin automatically refreshes expired tokens using the refresh token
    • LSP is updated with new tokens without restart
  3. LSP Integration:

    • Plugin configures and starts the GitLab LSP server
    • Listens for token validation errors from the server
    • Automatically handles token refresh when needed

🐛 Troubleshooting

Authentication fails

" Check if you have network access to GitLab
:GitLabAuth

" Enable debug logging
:lua require('gitlab-lsp').config.log_level = 'debug'

" Check messages for detailed errors
:messages

LSP not starting

" Check if token exists
:GitLabTokenInfo

" Manually start LSP
:GitLabStart

" Check LSP status
:LspInfo

Code suggestions not appearing

  1. Ensure you have a valid GitLab Duo license
  2. Check that your project is not excluded from Duo features
  3. Verify the file type is supported:
    :echo &filetype
  4. Check LSP logs:
    :lua vim.cmd('edit ' .. vim.lsp.get_log_path())

Token expired

The plugin automatically refreshes tokens, but if you encounter issues:

" Manually refresh
:GitLabRefreshToken

" Or re-authenticate
:GitLabLogout
:GitLabAuth

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • GitLab for providing the GitLab LSP and Duo AI features
  • Neovim for the excellent LSP support
  • plenary.nvim for async utilities

📚 Related Projects

💬 Support

About

Unofficial neovim plugin to wrap gitlab Language server with OAuth

Resources

Stars

Watchers

Forks

Contributors

Languages