# josefalbers/vim-lm architecture

> Architecture diagram of the GitHub repository josefalbers/vim-lm, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/josefalbers/vim-lm
- Repository: https://github.com/josefalbers/vim-lm

## Overview

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`](https://github.com/josefalbers/vim-lm/blob/main/vimlm.py) (vimlm.py), [`setup.py`](https://github.com/josefalbers/vim-lm/blob/main/setup.py) (setup.py), [`requirements.txt`](https://github.com/josefalbers/vim-lm/blob/main/requirements.txt) (requirements.txt)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_editor["Editor surface"]
  node_vim["Vim / NeoVim<br/>editor host"]
  node_keymaps["Keymaps<br/>mode bindings"]
  node_command["VimLM cmd<br/>ex-command"]
end

subgraph group_engine["VimLM engine"]
  node_engine_py["vimlm.py<br/>core orchestrator<br/>[vimlm.py]"]
  node_directives["Directives<br/>workflow DSL"]
  node_prompts["Prompt builder<br/>context composer"]
  node_session["Session state<br/>thread memory"]
end

subgraph group_context["Context sources"]
  node_buffer_ctx["Buffer state<br/>editor context"]
  node_file_ctx["File context<br/>repo context"]
  node_include_src["Include inputs<br/>directive source"]
  node_repo[("Project tree<br/>filesystem")]
  node_shell["Shell output<br/>command output"]
end

subgraph group_runtime["Local model"]
  node_llm(("Local LLM<br/>MLX inference"))
  node_config["cfg.json<br/>user config"]
end

subgraph group_output["Outputs"]
  node_insert["Insert text<br/>buffer write"]
  node_replace["Replace selection<br/>edit action"]
  node_deploy["Deploy files<br/>filesystem write"]
end

subgraph group_packaging["Packaging"]
  node_setup["setup.py<br/>package metadata<br/>[setup.py]"]
  node_deps["requirements.txt<br/>dependencies<br/>[requirements.txt]"]
end

node_vim -->|"uses"| node_keymaps
node_vim -->|"issues"| node_command
node_keymaps -->|"invokes"| node_engine_py
node_command -->|"dispatches"| node_engine_py
node_engine_py -->|"parses"| node_directives
node_engine_py -->|"builds"| node_prompts
node_directives -->|"expands"| node_include_src
node_prompts -->|"reads"| node_buffer_ctx
node_prompts -->|"reads"| node_file_ctx
node_prompts -->|"tracks"| node_session
node_include_src -->|"loads"| node_repo
node_include_src -->|"captures"| node_shell
node_prompts -->|"sends"| node_llm
node_config -->|"configures"| node_llm
node_llm -->|"returns"| node_engine_py
node_engine_py -->|"applies"| node_insert
node_engine_py -->|"applies"| node_replace
node_engine_py -->|"exports"| node_deploy
node_setup -->|"packages"| node_engine_py
node_deps -->|"supports"| node_engine_py

click node_engine_py "https://github.com/josefalbers/vim-lm/blob/main/vimlm.py"
click node_setup "https://github.com/josefalbers/vim-lm/blob/main/setup.py"
click node_deps "https://github.com/josefalbers/vim-lm/blob/main/requirements.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_vim,node_keymaps,node_command toneBlue
class node_engine_py,node_directives,node_prompts,node_session toneAmber
class node_buffer_ctx,node_file_ctx,node_include_src,node_repo,node_shell toneMint
class node_llm,node_config toneRose
class node_insert,node_replace,node_deploy toneIndigo
class node_setup,node_deps toneTeal
```

## Components

### Editor surface

Vim/NeoVim entry points and user-facing commands

- **Vim / NeoVim**: editor host · The interactive environment where VimLM runs as an embedded assistant
- **Keymaps**: mode bindings · Normal, visual, and insert mode bindings that trigger assistant actions
- **VimLM cmd**: ex-command · The :VimLM command interface and directive-driven prompt entry point

### VimLM engine

Prompt assembly, session handling, and response orchestration

- [vimlm.py](https://github.com/josefalbers/vim-lm/blob/main/vimlm.py): core orchestrator · Main Python entrypoint that coordinates prompt building, model calls, and result handling · `vimlm.py`
- **Directives**: workflow DSL · Inline commands such as !include, !deploy, !continue, and !followup
- **Prompt builder**: context composer · Combines editor state and directive inputs into model-ready prompts
- **Session state**: thread memory · Lightweight conversation continuity for follow-up prompts

### Context sources

Inputs gathered into prompts from the editor, repo, and shell

- **Buffer state**: editor context · Current buffer content, cursor position, and selection state
- **File context**: repo context · Current file, line reference, and repository paths supplied on invocation
- **Include inputs**: directive source · Files, directories, and shell output pulled in via !include
- **Project tree**: filesystem · Repository files and directories exposed to the prompt layer
- **Shell output**: command output · Text produced by command substitution and included in prompt context

### Local model

Offline inference and user configuration for generation

- **Local LLM**: MLX inference · Offline model execution expected on local Apple Silicon hardware
- **cfg.json**: user config · 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**: buffer write · Generated completion inserted into the current buffer
- **Replace selection**: edit action · Generated text substituted into the active visual selection
- **Deploy files**: filesystem write · Generated code exported to a destination directory via !deploy

### Packaging

Install and dependency metadata for the Python tool

- [setup.py](https://github.com/josefalbers/vim-lm/blob/main/setup.py): package metadata · Python packaging and install entry definition · `setup.py`
- [requirements.txt](https://github.com/josefalbers/vim-lm/blob/main/requirements.txt): dependencies · Runtime Python dependency set · `requirements.txt`

## Connections

- 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
