How josefalbers/vim-lm works
1. What this repo is
- VimLM is a local AI assistant for Vim/NeoVim.
- The repository is very small: the core behavior is centered in a single Python entrypoint, vimlm.py, with packaging in setup.py and runtime dependencies in requirements.txt.
2. Primary runtime shape
- This is not a client-server app.
- The user runs a Python CLI/tooling process that integrates into an already-running Vim or NeoVim session.
- The editor remains the UI; VimLM acts as the local orchestration layer between editor state and the language model.
3. Main boundary: editor ↔ assistant
- The key architectural boundary is the one between:
- Vim/NeoVim state: current file, cursor position, visual selection, inserted text
- VimLM orchestration: prompt building, context gathering, response handling
- This boundary is exercised through normal/visual/insert mode keybindings and the :VimLM command.
4. Context assembly pipeline
- VimLM builds prompts from multiple context sources:
- current buffer / selected code
- current file and line
- repository paths passed with --repo
- explicit !include directives for files, directories, or shell command output
- This context layering is a core part of the architecture because it determines what the model can “see.”
5. LLM execution layer
- The assistant is designed for offline-first local inference.
- The README ties it to Apple Silicon and MLX-compatible models, which means model execution is expected to happen locally on the user’s machine rather than via a remote API.
- The model settings live in a user config file at ~/vimlm/cfg.json, including model name and token limits.
6. Interaction modes
- There are two major workflows:
- Autocomplete: generate code at the cursor and optionally insert it
- Conversational assistance: ask for broader changes, continue threads, and replace selections
- These are surfaced through different keybindings depending on Vim mode, but they share the same underlying prompt/response pipeline.
7. Response handling and code application
- Generated output is not just displayed; it can be:
- inserted into the current buffer
- substituted into a visual selection
- saved out to a destination directory via !deploy
- That means VimLM sits at the boundary between text generation and filesystem mutation.
8. Command chaining / directive system
- The :VimLM ... command supports inline directives like !include, !deploy, !continue, and !followup.
- Architecturally, this turns a single prompt into a mini workflow language for composing context, extending generations, and exporting code blocks.
9. Conversation state
- The README describes “continue conversation” behavior, implying VimLM tracks at least a lightweight session/thread state for follow-up prompts.
- This is important for diagramming because the system is not stateless autocomplete; it supports iterative interaction across prompts.
10. Repository and shell integration
- !include can pull in:
- file contents
- whole directories
- shell output via substitution
- This makes VimLM a bridge across three domains: editor text, project filesystem, and command-line output.
11. Distribution and packaging
- setup.py indicates this is packaged as an installable Python tool, likely exposing the vimlm CLI.
- requirements.txt defines the runtime Python dependency set, so the repo’s deployment boundary is primarily Python package installation rather than a service deployment.
12. Non-goals / absent subsystems
- There is no evidence of:
- a database
- a web frontend
- a background daemon/server
- cloud authentication or remote API orchestration
- The architecture is intentionally compact: editor plugin behavior plus local model orchestration.
13. How to draw it
- A good architecture diagram would show:
- User in Vim/NeoVim
- Vim keybindings / :VimLM command
- Python VimLM engine (vimlm.py)
- Context sources: buffer, selection, files, repo paths, shell commands
- Local LLM runtime on Apple Silicon via MLX-compatible model
- Output actions: insert into buffer, replace selection, deploy to files/directories
- Config file ~/vimlm/cfg.json
14. Overall design takeaway
- VimLM is a local, mode-aware, prompt-composing assistant embedded into Vim rather than an external IDE service.
- Its architecture is defined by editor integration, context collection, local inference, and code application back into the filesystem/editor.
Main entry points: vimlm.py vimlm.py · setup.py setup.py · requirements.txt requirements.txt
Components 19
Editor surface
Vim/NeoVim entry points and user-facing commands
- Vim / NeoVim · The interactive environment where VimLM runs as an embedded assistant
- Keymaps · Normal, visual, and insert mode bindings that trigger assistant actions
- VimLM cmd · The :VimLM command interface and directive-driven prompt entry point
VimLM engine
Prompt assembly, session handling, and response orchestration
- vimlm.py · Main Python entrypoint that coordinates prompt building, model calls, and result handling
vimlm.py - Directives · Inline commands such as !include, !deploy, !continue, and !followup
- Prompt builder · Combines editor state and directive inputs into model-ready prompts
- Session state · Lightweight conversation continuity for follow-up prompts
Context sources
Inputs gathered into prompts from the editor, repo, and shell
- Buffer state · Current buffer content, cursor position, and selection state
- File context · Current file, line reference, and repository paths supplied on invocation
- Include inputs · Files, directories, and shell output pulled in via !include
- Project tree · Repository files and directories exposed to the prompt layer
- Shell output · Text produced by command substitution and included in prompt context
Local model
Offline inference and user configuration for generation
- Local LLM · Offline model execution expected on local Apple Silicon hardware
- cfg.json · User settings for model name and token limits stored in ~/vimlm/cfg.json
Outputs
How generated text is applied back into the editor or filesystem
- Insert text · Generated completion inserted into the current buffer
- Replace selection · Generated text substituted into the active visual selection
- Deploy files · Generated code exported to a destination directory via !deploy
Packaging
Install and dependency metadata for the Python tool
- setup.py · Python packaging and install entry definition
setup.py - requirements.txt · Runtime Python dependency set
requirements.txt
Connections 20
- Vim / NeoVim → Keymaps: uses · User triggers assistant flows through mode-specific shortcuts
- Vim / NeoVim → VimLM cmd: issues · The :VimLM command is entered from the editor
- Keymaps → vimlm.py: invokes · Bindings route into the core Python orchestration layer
- VimLM cmd → vimlm.py: dispatches · Command execution enters the main engine
- vimlm.py → Directives: parses · Inline directives shape the workflow for a request
- vimlm.py → Prompt builder: builds · Core engine assembles the prompt payload
- Directives → Include inputs: expands · !include and related directives add external context
- Prompt builder → Buffer state: reads · Prompt assembly pulls current editor state
- Prompt builder → File context: reads · Prompt assembly includes file and repository location context
- Prompt builder → Session state: tracks · Conversation continuity is preserved across requests
- Include inputs → Project tree: loads · Included file and directory content comes from the project tree
- Include inputs → Shell output: captures · Command substitution contributes shell-produced text
- Prompt builder → Local LLM: sends · Prepared prompt is submitted to local inference
- cfg.json → Local LLM: configures · User settings select model and generation limits
- Local LLM → vimlm.py: returns · Generated output flows back to the Python engine
- vimlm.py → Insert text: applies · Autocomplete output can be inserted into the active buffer
- vimlm.py → Replace selection: applies · Conversation output can replace a selection
- vimlm.py → Deploy files: exports · Generated blocks can be written to destination directories
- setup.py → vimlm.py: packages · Packaging exposes the CLI entrypoint and installable tool
- requirements.txt → vimlm.py: supports · Declared runtime dependencies support execution