Skip to content

isaksamsten/sia.nvim

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Logo

sia.nvim

An LLM assistant for Neovim.

Supports: OpenAI, Copilot and Gemini (and any other OpenAI API compliant LLM).

Default configuration has the following models: gpt-4o, gpt-4o-mini, o3-mini, copilot-gpt-4o, copilot-o3-mini, copilot-sonnet-3.5, gemini-1.5-flash-8b, gemini-1.5-flash, gemini-2.0-flash-exp and gemini-1.5-pro.

✨ Features

Screen.Recording.2025-02-20.at.20.50.16.mov
Screen.Recording.2025-02-10.at.12.39.24.mov
Screen.Recording.2024-10-22.at.12.15.13.mov
Screen.Recording.2024-10-10.at.15.59.41.mov
Screen.Recording.2024-10-11.at.15.42.20.mov
Screen.Recording.2024-10-16.at.15.52.59.mov

⚡️ Requirements

  • Neovim >= 0.10
  • curl
  • Access to OpenAI API, Copilot or Gemini

📦 Installation

  1. Install using a Lazy:
{
  "isaksamsten/sia.nvim",
  opts = {},
  dependencies = {
    {
      "rickhowe/diffchar.vim",
      keys = {
        { "[z", "<Plug>JumpDiffCharPrevStart", desc = "Previous diff", silent = true },
        { "]z", "<Plug>JumpDiffCharNextStart", desc = "Next diff", silent = true },
        { "do", "<Plug>GetDiffCharPair", desc = "Obtain diff", silent = true },
        { "dp", "<Plug>PutDiffCharPair", desc = "Put diff", silent = true },
      },
    },
  },
}
  1. get an OpenAI API key and add it to your environment as OPENAI_API_KEY, enable Copilot (use the vim plugin to set it up) or add Gemini API key to your environment as GEMINI_API_KEY.

📦 Customize

TODO

Autocommands

sia.nvim emits the following autocommands:

  • SiaUsageReport: when the number of tokens are known
  • SiaStart: query has been submitted
  • SiaProgress: a response has been received
  • SiaComplete: the query is completed
  • SiaError: on errors in the LLM
  • SiaEditPost: after a buffer has been edited

🚀 Usage

Normal Mode

  • :Sia [query] - Sends the query and opens a split view with the response.

  • :Sia [query] (from a conversation) - Continues the conversation with the new query.

  • :Sia /prompt [query] - Executes the prompt with the optional additional query.

  • :Sia! [query] - Sends the query and inserts the response directly into the buffer.

  • :SiaFile - Displays the files in the global file list; if run from a split, shows the files associated with the current conversation.

  • :SiaFile patterns - Adds files matching the specified patterns to the global file list; if run from a split, adds them to the current conversation.

  • :SiaFileDelete patterns - Removes files matching the specified patterns from the global file list; if run from a split, removes them from the current conversation.

  • :SiaAccept - Accepts a suggested edit.

  • :SiaReject - Rejects a suggested edit.

Ranges

Any range is supported. For example:

  • :'<,'>Sia! [query] - Sends the selected lines along with the query and diffs the response.
  • :'<,'>Sia [query] - Sends the selected lines and query, opening a split with the response.
  • :'<,'>Sia /prompt [query] - Executes the prompt with the extra query for the selected range.

Examples

  • :%Sia fix the test function - Opens a split with a suggested fix for the test function.
  • :Sia write snake in pygame - Opens a split with the generated answer for the query.
  • :Sia /doc numpydoc - Documents the function or class under the cursor using the numpydoc format.
  • :SiaFile a.py b.py | Sia move the function foo_a to b.py - Moves the function foo_a from a.py to b.py.
  • :%Sia /diagnostic - Opens a split with a solution to diagnostics in the current file.

Suggested Keybindings

You can bind visual and operator mode selections to enhance your workflow with sia.nvim:

  • Append Current Selection:
    • <Plug>(sia-append) - Appends the current selection or operator mode selection to the visible split.
  • Execute Default Prompt:
    • <Plug>(sia-execute) - Executes the default prompt (vim.b.sia) with the current selection or operator mode selection.
keys = {
  { "gza", mode = { "n", "x" }, "<Plug>(sia-append)" },
  { "gzz", mode = { "n", "x" }, "<Plug>(sia-execute)" },
}

You can send the current paragraph to the default prompt using gzzip or append the current method (assuming treesitter-textobjects) to the ongoing chat with gzaam.

Sia also creates Plug bindings for all actions using <Plug>(sia-execute-<ACTION>), for example, <Plug>(sia-execute-explain) for the default action /explain.

keys = {
  { "gze", mode = { "n", "x" }, "<Plug>(sia-execute-explain)" },
}

Chat Mappings

In the split view (with ft=sia), you can bind the following mappings for efficient interaction:

keys = {
  { "cp", mode = "n", "<Plug>(sia-peek-context)", ft = "sia" },
  { "cx", mode = "n", "<Plug>(sia-delete-instruction)", ft = "sia" },
  { "gr", mode = "n", "<Plug>(sia-replace-block)", ft = "sia" },
  { "gR", mode = "n", "<Plug>(sia-replace-all-blocks)", ft = "sia" },
  { "ga", mode = "n", "<Plug>(sia-insert-block-above)", ft = "sia" },
  { "gb", mode = "n", "<Plug>(sia-insert-block-below)", ft = "sia" },
  { "<CR>", mode = "n", "<Plug>(sia-reply)", ft = "sia" },
}
  • View Context: <Plug>(sia-peek-context) - View each context added to the chat.
  • Delete Instruction: <Plug>(sia-delete-instruction) - Remove instructions from the chat.
  • Replace Block: <Plug>(sia-replace-block) - Apply the suggested edit when the cursor is on a code block.
  • Replace All Blocks: <Plug>(sia-replace-all-blocks) - Apply suggested edits to all code blocks in the chat and open a quickfix list.
  • Insert Block Above: <Plug>(sia-insert-block-above) - Insert a code block above the cursor.
  • Insert Block Below: <Plug>(sia-insert-block-below) - Insert a code block below the cursor.
  • Compose Longer Query: <Plug>(sia-reply) - Open a split view to compose a longer query.

Accepting and Rejecting Suggestions

When inserting suggestions, Sia will create markers in the code that need to be accepted or rejected.

Consider using conflicting.nvim to highlight and resolve the conflicts.

Add conflicting.nvim to dependencies (or separately to also deal with Git merges), and setup an auto command:

vim.api.nvim_create_autocmd("User", {
  pattern = "SiaEditPost",
  callback = function(args)
    local buf = args.data.buf
    if buf then
      require("conflicting").track(buf)
    end
  end,
})

Markers will look like this when replacing all blocks:

<<<<<<< User
def range_inclusive(start, end):
    return list(range(start, end + 1))

def range_exclusive(start, end):
    return list(range(start, end))

def range_with_step(start, end, step):
    return list(range(start, end, step))

=======
from ranges import range_inclusive, range_exclusive, range_with_step
>>>>>>> Sia

If you are using conflicting.nvim, you can accept the suggestion from Sia with Conflicting incoming (or for all changes in the quickfix list with :cdo Conflicting incoming)

Customize configuration

Default actions

In Sia, you can execute various actions using the command :Sia <action>. The following actions are bundled in the default configuration:

  • edit: Edit a selection without confirmation using the instructions.

    • Example: '<,'>Sia /edit optimize
  • diagnostic: Open a split window with explanations for the diagnostics in the specified range.

    • Example: '<,'>Sia /diagnostic
  • commit: Insert a commit message (enabled only if inside a Git repository and the current file type is gitcommit).

    • Example: Sia /commit
  • review: Review the code in the specified range and open a quickfix window with comments.

    • Example: '<,'>Sia /review
  • explain: Open a split window explaining the current range.

    • Example: '<,'>Sia /explain focus on the counter
  • unittest: Open a split window with unit tests for the current range or the captured function under the cursor.

  • doc: Insert documentation for the function or class under the cursor.

    • Example: Sia /doc
  • fix: Inline fix for the issue provided in a quickfix window.

    • Example: Sia /fix

Customizing actions

See lua/sia/actions.lua for example actions. Here is a short snippet with a simple action.

require("sia").setup({
  actions = {
    yoda = {
      mode = "split", -- Open in a split
      split = { cmd = "split" }, -- We want an horizontal split
      instructions = {
        -- Custom system prompt
        {
          role = "system",
          content = "You are a helpful writer, rewriting prose as Yoda.",
        },
        "current_context", -- builtin instruction to get the current selection
      }
      range = true, -- A range is required
    },

    -- customize a built in instruction ()
    fix = require("sia.actions").fix({split = true})
  }
})

We can use it with Sia /yoda.

About

A simple assistant for Neovim

Resources

License

Stars

Watchers

Forks

Languages

  • Lua 100.0%