Files
vim/AGENTS.md
T
Christian Brabandt 1de887681d No guidance for AI coding agents
Problem:  No guidance for AI coding agents working in the Vim
          repository.
Solution: Add AGENTS.md to the repository documenting build
          and test commands, repository layout, commit format,
          C and Vim9-script conventions, test conventions, help
          file style, and release policy, so that AI agents can
          produce patches that match project expectations.

closes: #20039

Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-26 08:11:59 +00:00

15 KiB

AGENTS.md

Guidance for AI coding agents working in the Vim repository.

Project

Vim is a text editor written in C. The canonical repository is https://github.com/vim/vim. The code is old and has grown organically over the past 30+ years. Some files are vendored from upstream projects (src/xdiff, src/libvterm); parts of the runtime are occasionally shared with forks like Neovim.

Vim strives to be portable across several different operating systems and aims to be a stable, robust editor gradually developing new features while remaining backwards compatible as much as possible.

At the same time, Vim can be compiled with different feature sets, from the POSIX compatible minimal vi to a full-fledged GUI editor which includes additional scripting interfaces.

See runtime/doc/develop.txt for the high level design goals.

Build and test

# Full build on Unix/Linux (from src/):
make

# Run the full test suite:
make test

# Generate proto files
make proto

# Run a single test file:
cd src/testdir && make test_name.res

Output is in testdir/messages and testdir/test.log

Builds on Windows depend on the Environment, see src/INSTALLpc.txt for Cygwin/MSYS and MSVC ways to build Vim

Before submitting any patch, at minimum:

  1. The build succeeds without new warnings.
  2. Relevant tests pass.
  3. The code matches the style of the file being edited.

Layout

  • src/ - the C source. Subsystem names are usually obvious from filenames (buffer.c, window.c, search.c, vim9compile.c, etc.).
  • src/proto/ - function prototypes, one .pro file per source file. Regenerated; do not hand-edit unless you know what you're doing.
  • src/po - Translations
  • src/xxd - for the xxd subproject
  • src/xdiff - for the xdiff library (imported from git)
  • src/libvterm - for the libvterm library
  • src/testdir/ - tests. Vim-script files named test_*.vim. Screendump expected output lives in src/testdir/dumps/.
  • runtime/doc/ - user-facing documentation in Vim help format, when updating, also update the Last Change header
  • runtime/syntax/generator - Syntax script for Vim Script, automatically generated from Vims source
  • runtime/ - runtime files shipped with Vim, when updating, also update the Last Change header and a short description if this file has no maintainer If the file has a maintainer, changes should go via them (so make a merge request against the upstream repo instead)
  • src/version.c - contains the included_patches[] list. Every patch touching anything below src/ (with the exception of src/po) needs a new entry at the top, will be updated only when merging into the master tree.

Commit format

Vim uses a strict commit message format. The subject line is a one-sentence problem statement, not a description of the fix:

patch 9.2.NNNN: short description of the problem

Problem:  Restatement of the problem as a full sentence, possibly
          with a reporter attribution in parentheses.
Solution: Short description of the fix, ending with the author's
          name in parentheses.

optional longer description of the problem and solution goes here in prose.
Do not use bullet points.

fixes:   #NNNN
related: #NNNN
closes:  #NNNN

Co-authored-by: Name
Signed-off-by: Author Name <email>

Rules:

  • Subject line states the problem, not the solution. "fix typo" is wrong; "typo in foo() causes OOB read" is right.
  • Problem line is a full sentence with a trailing period. It mirrors the subject.
  • Solution line ends with (Author Name) — parentheses, period after them.
  • Longer prose, if any, goes after the Problem/Solution header
  • fixes: references the issue the patch fixes. closes: references the PR that introduces the fix. related: references related issues, including issues that caused this one. All can appear. Colon, aligned, no trailing period.
  • Signed-off-by: is required — DCO.
  • Co-Authored-By: is allowed and is the accepted way to acknowledge AI assistance transparently. Human coauthors should usually also have their own Signed-off-by.

C code conventions

  • Indentation is 4 spaces per level. Existing files use tabs with ts=8 sts=4 sw=4 noet (set by the modeline in the file), so tabs of width 8 appear where two levels of indent collapse. sign.c, sound.c, and any new file must use spaces only and follow the style from the .editorconfig file.
  • Opening braces go on their own line (Allman style) — for function definitions and for control-flow constructs (if/else/for/while/ do) alike.
  • Function definitions: return type on its own indented line, with the function name beginning on the next line.
  • Initialize locals where a reader cannot trivially see the first assignment (common for pointers and return-value accumulators). Don't add = 0 initializers for values that are always assigned before use — they can hide real uninitialized-read bugs from the compiler.
  • for (int i = 0; ...) loop declarations are fine in files that use them; older files may declare the counter at the top of the block.
  • Function-scope declarations at the top of a block is the historical style, but mid-block declarations are acceptable in files that have adopted them. Match the surrounding code.
  • Custom types end in _T (e.g., buf_T, linenr_T, pos_T). Never use _t — it collides with POSIX typedefs.
  • C language is C95 plus specific C99 features: // comments, mixed declarations and statements, __func__, bool/_Bool, variadic macros, compound literals, static inline, trailing enum commas. Do not reach for later C standards — Vim still must build with Compaq C on OpenVMS. See *assumptions-C-compiler* in develop.txt for the full list.
  • bool / true / false are acceptable. Vim is transitioning from int with TRUE/FALSE to C99 bool. Do not "fix" bool back to int. Within a single patch, be consistent — don't mix true and TRUE in new code.
  • Do not mass-convert TRUE/FALSE to true/false across files unless that is the patch's explicit purpose. Opportunistic conversions create noise in diffs.
  • STRLEN_LITERAL("...") should be used when the length of a string literal is needed. Avoid STRLEN() on literals.
  • vim_snprintf_safelen() returns the written length; prefer it over vim_snprintf() when the length is then needed.
  • Prefer dict_add_string_len() when the string length is already known, over dict_add_string() which calls STRLEN().
  • String/buffer parameters go (char_u *buf, size_t buflen) — length alongside pointer, in bytes. Use size_t for byte counts, int only where required by legacy APIs.
  • Guards before divisions. Check for divisor zero explicitly, even when a composite earlier guard would prevent it. Relying on transitive guards is fragile.
  • When introducing new allocations, verify the cleanup paths handle all exit conditions (early return, error branches, etc).

Use Vim wrappers instead of libc where one exists:

libc Vim Why
free() vim_free() Tolerates NULL
malloc() alloc() / lalloc() Checks for OOM
strcpy() STRCPY() Cast for char_u *
strchr() vim_strchr() Handles special characters
strrchr() vim_strrchr() Handles special characters
memcpy() mch_memmove() Handles overlapping copies
bcopy() mch_memmove() Handles overlapping copies
memset() vim_memset() Uniform across systems
isspace() vim_isspace() Handles bytes > 127
iswhite() vim_iswhite() TRUE only for tab and space

Further rules, not spelled out here, live in runtime/doc/develop.txt:

  • *style-names* — reserved name patterns (is*, to*, str*, mem*, wcs*, .*_t, __.*), forbidden identifiers (delete, this, new, time, index), and the 31-character function-name limit.
  • *style-spaces*, *style-examples* — spacing and one-statement-per-line.
  • *style-various*FEAT_ feature prefix, uppercase #define, #ifdef HAVE_X rather than #if HAVE_X, no '\"'.
  • *assumptions-makefiles* — POSIX.1-2001 make only in the main Makefiles (no % rules, :=, .ONESHELL, GNU conditionals).
  • Vim uses char_u instead of char type
  • Vim uses the macros STRLEN, STRCPY, STRCMP, STRCAT that work with the char_u type.
  • *style-clang-format*sign.c and sound.c are formatted with clang-format; re-run it after editing those files.

Vim9 script conventions (in tests and runtime files)

  • Write modern Vim style (new files can use Vim9 script, but compatibility with Neovim and other forks is a concern, so in doubt please ask!)
  • Drop l: prefix from local variables in Vim-script tests.
  • Don't add CheckFeature inside individual tests if it's already at the top of the file.
  • If a test file doesn't gate features at the top, add CheckFeature to individual tests that depend on specific build features.

Test conventions

  • Tests are in src/testdir/test_*.vim.
  • Reproducible tests beat "it doesn't crash" tests. If a patch fixes a rendering bug, add a screendump test. If it fixes incorrect output, assert the output.
  • Add comprehensive tests for newly added features and include them in existing tests if possible
  • Screendump tests use CheckScreendump, RunVimInTerminal, VerifyScreenDump, and live dumps in src/testdir/dumps/.
  • v9.CheckScriptSuccess(lines) / v9.CheckScriptFailure(lines, error, lnum) are the standard way to test Vim9 script behavior at script-load time.
  • When fixing a bug reported as an issue, include a test that reproduces the original report, not just a minimal synthetic case.
  • Tests for Syntax runtime are in runtime/syntax/testdir
  • Tests for Indent runtime are in runtime/indent/testdir

Common gotchas

  • Distinguish what code enforces from what docs claim. If a patch changes documented behavior, say so in the Problem/Solution.
  • Generated files (src/auto/configure, generated Wayland protocol C, etc.) should only be regenerated when their source changes. Mixing unrelated regeneration into a functional patch creates noise.

Documentation

  • User-facing option or feature changes require a runtime/doc/*.txt update in the same patch.
  • When editing an existing help file, bump the Last change: header at the top.

Help file style

See runtime/doc/helphelp.txt (*help-writing*) for the authoritative reference. Key conventions:

  • File header: first line is *filename.txt* then a tab then a short description. That description appears under LOCAL ADDITIONS in help.txt. The version and Last change: date go on the second line, right aligned.
  • Modeline: every help file ends with a Vim modeline — typically vim:tw=78:ts=8:noet:ft=help:norl:.
  • Layout: 'textwidth' 78, 'tabstop' 8, indent and align with tab characters. Two spaces between sentences. Run :retab (not :retab!, and review the diff) after editing.
  • Tags are defined as *tag-name*, usually right-aligned on the line where the thing they name is introduced. Tag names must be unique across all of runtime/doc/; for plugin help, prefix with the plugin name.
  • Cross-references inside help text:
    • |tag-name| — hot-link to an existing tag.
    • `:cmd` — Ex command, highlighted as a code block.
    • 'option' — option name, in single quotes.
    • <Key> or CTRL-X — special keys.
    • {placeholder} — user-supplied argument.
  • Sections are separated by a line of = starting in column 1. Column or subsection headings end with ~ to trigger heading highlighting.
  • Code blocks start with > at the end of the introducing line and end with < as the first non-blank on a later line (any line starting in column 1 also implicitly closes the block). Use >vim (or another language name) to request syntax highlighting inside the block.
  • NotationNote, Todo, Error and a few similar words are auto-highlighted; do not try to fake the highlighting by other means.
  • Language: gender-neutral language is preferred for new or updated text; existing wording does not need to be rewritten for this alone.

Release policy

Vim alternates between development cycles and stability periods — see runtime/doc/develop.txt *design-policy*.

  • During a stability period only clear bug fixes, security fixes, documentation updates, translations, and runtime file updates are accepted. No new features, no backwards-incompatible changes.
  • Once released in a minor version, C-core features must stay backwards-compatible. Runtime files have a bit more flexibility so their maintainers can correct old behavior.
  • Deprecated features stay reachable via config (do not hard-error), are documented as deprecated, can be disabled at compile time, and may be removed in a later cycle.

Security

Before reporting a suspected security issue or submitting a patch that touches security-sensitive code, read SECURITY.md. Follow the disclosure process described there.

Before submitting

  1. Commit message follows the format above.
  2. All modified code compiles without new warnings.
  3. Tests pass, and new functionality has regression tests.
  4. Documentation is updated for user-visible changes.
  5. Signed-off-by is present.
  6. Diff contains only changes relevant to the stated problem — no stray whitespace fixes, no unrelated refactors, no unrelated regeneration of auto/configure.
  7. For multi-patch series: each commit compiles and passes its own tests. A known-broken intermediate state that a later patch fixes is not acceptable — squash instead.

When in doubt

  • Make the smallest possible change to achieve the goal. Do not rewrite entire files or functions when a targeted edit suffices.
  • Read surrounding code and match its style rather than imposing an "improvement."
  • Err toward smaller, more focused patches. A patch that does three things is three patches.
  • If a patch fixes a symptom of a deeper bug, say so in the Problem and acknowledge the scope limitation in the Solution.
  • Before claiming a bug exists, reproduce it. Before claiming code does X, read the code. Do not rely on training-data memory of file contents.
  • Before running shell commands that modify files outside the working tree, install packages, push branches, or invoke network operations, confirm with the user.