--- /dev/null
+# 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.
+- **Notation** — `Note`, `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.