Maintain cargo.nvim
Preserve the native-module ABI and supported editor/toolchain matrix while
keeping changes easy to validate in a real Neovim host.
Inspect before editing
- Read
AGENTS.md, Cargo.toml, .cargo/config.toml, the affected source,
and the relevant workflow.
- Inspect
jj st and jj diff --stat; preserve unrelated changes.
- Re-check current official documentation before changing a library, Neovim
API, GitHub Action, or compatibility claim. Do not assume versions in this
skill are the latest.
- Apply the required shell-command wrapper from higher-level instructions to
every command.
Manage the compatibility contract
- Keep Rust/Cargo 1.97, Edition 2024, and Neovim 0.9 as the default minimum
versions.
- Allow an explicit compatibility or architecture change requested by the
user. Update the manifest, runtime guards, README claims, CI coverage, and
regression tests together; do not leave the old contract implied elsewhere.
- Distinguish a current implementation pattern from an invariant. A redesign
may replace the implementation guidance below when it preserves the native
ABI, command safety, lifecycle guarantees, and declared compatibility with
equivalent tests.
- Treat the native ABI and mlua module mode as strong defaults, not absolute
prohibitions. Change either only when the user explicitly requests that
boundary, and include a loader/build migration plus cross-platform tests.
Preserve native and command-safety invariants
Rust and native module
- Keep
rust-version = "1.97" and Edition 2024 unless compatibility is being
changed intentionally. Keep Cargo.lock synchronized and use --locked in
reproducible build and CI commands.
- Keep
mlua in module mode. Neovim supplies the Lua symbols at runtime; do
not add a build.rs, pkg-config lookup, or direct Lua/LuaJIT library link.
- Keep
unsafe_op_in_unsafe_fn and clippy::undocumented_unsafe_blocks
denied in Cargo.toml. Document the proof obligation for any necessary
unsafe block. Add other Clippy lints individually; do not enable the complete
pedantic or restriction groups.
- Preserve the macOS dynamic-lookup flags in
.cargo/config.toml. Do not set a
workflow-level RUSTFLAGS, because it overrides target rustflags from Cargo
configuration.
- Treat
luajit and lua51 as mutually exclusive. Never validate with
--all-features; run each feature configuration separately.
- Enable only the Tokio features used by the source.
- Spawn Cargo without a shell. Keep user arguments as
Vec<String>/Lua lists.
- Terminate Cargo and its descendants as one process group on Unix and one Job
Object on Windows. Await/reap the worker and retain a deterministic
long-running cancellation test.
Lua and Neovim
- While retaining Neovim 0.9 compatibility, guard APIs introduced or changed in
later versions. The current implementation preserves the
vim.validate
compatibility path and uses jobstart(..., { term = true }) only on Neovim
0.11+, with termopen for 0.9/0.10.
- Keep
setup() idempotent. Clear only plugin-owned commands and autocmds.
- Prefer the current named augroups, autocmd descriptions,
vim.keymap.set,
buffer-local Lua callbacks, and mapping descriptions.
- When preserving the current buffer lifecycle, configure plugin-owned buffers
before setting
filetype, then let the FileType event apply buffer-local
syntax and options.
- Prefer highlight links to standard groups with
default = true and restore
them after ColorScheme.
- Use
args.fargs and argv lists. Do not split or concatenate user input into a
shell command.
- The current loader uses
package.loadlib and caches the returned module.
Test any replacement in Neovim. Do not instantiate a standalone mlua::Lua
in Rust tests: module mode deliberately leaves host Lua symbols unresolved.
CI and release
- Pin third-party GitHub Actions to immutable commit SHAs, disable checkout
credentials when unused, set minimal permissions, and keep timeouts.
- Keep Rust checks for the minimum toolchain and stable. Run tests/builds on
Linux, macOS, and Windows; run headless Neovim integration on supported CI
hosts where Neovim is installed.
- Run Clippy and tests for the mutually exclusive
luajit and lua51
configurations separately.
- Keep the Linux integration leg pinned to Neovim 0.9.5 and exercise a current
Neovim release on macOS.
- Keep workflow path filters synchronized with every file class a job validates.
In particular, Rust integration coverage must react to both
lua/ and
plugin/ runtime changes.
- Run headless integration as
nvim --headless -u NONE -l tests/integration.lua. Do not use
+lua dofile(...), which can hide Lua assertion failures behind a successful
process exit.
- For a version bump, update both the package version in
Cargo.toml and the
root package entry in Cargo.lock. Do not create a tag or release unless the
user explicitly requests it.
Validate changes
Run the relevant subset while iterating, then run the full local suite before
publishing. The following are logical commands; prefix each one with the active
shell wrapper required by higher-level instructions:
cargo fmt --all -- --check
cargo clippy --locked --all-targets -- -D warnings
cargo clippy --locked --all-targets --no-default-features --features lua51 -- -D warnings
cargo test --locked
cargo +1.97.0 check --locked
cargo +1.97.0 check --locked --no-default-features --features lua51
cargo check --locked --no-default-features --features lua51
cargo test --locked --no-default-features --features lua51
cargo build --locked --release
stylua --check lua plugin tests
luacheck lua plugin tests
busted tests/command_spec.lua
nvim --headless -u NONE -l tests/integration.lua
actionlint .github/workflows/*.yml
git diff --cached --check
git diff --check
Treat the explicit Rust 1.97 check as required MSRV evidence. If that toolchain
is unavailable locally, require the CI MSRV job and report the local skip.
Record nvim --version. Run integration on Neovim 0.9 when that executable is
available. A newer-Neovim pass does not prove the minimum; when 0.9 is not
available locally, require the pinned Linux CI result as minimum-version
evidence.
On macOS, inspect the release artifact when native linking changes:
otool -L target/release/libcargo_nvim.dylib
Confirm that it does not link a Homebrew or system Lua/LuaJIT library.
Run tests/command_spec.lua with Busted when the local Lua installation is
healthy. The headless integration must still cover the command helper and the
actual native module in Neovim's LuaJIT host.
Complete the task
- Reinspect
jj st, the final diff, version metadata, and generated files.
- Report each command actually run and its observed result. Identify skipped
platform checks explicitly.
- When asked to publish, use the repository's jj publishing skill. Confirm the
final
main/main@origin hash. Derive expected workflows from the changed
paths and each workflow's path filters, then wait for those runs. If an
expected run is absent, report it; do not manually dispatch a workflow unless
the user authorized that external action.
1---2name: maintain-cargo-nvim3description: Maintain cargo.nvim's Rust native module, Lua/Neovim runtime, build configuration, tests, CI, dependencies, documentation, release tooling, and version metadata. Use when changing Cargo.toml, Cargo.lock, .cargo/config.toml, src/, lua/, plugin/, tests/, README.md compatibility or usage claims, Release.sh, GitHub workflows, Neovim compatibility, process execution or cancellation, native-module linking, dependency versions, or releases.4---56# Maintain cargo.nvim78Preserve the native-module ABI and supported editor/toolchain matrix while9keeping changes easy to validate in a real Neovim host.1011## Inspect before editing12131. Read `AGENTS.md`, `Cargo.toml`, `.cargo/config.toml`, the affected source,14 and the relevant workflow.152. Inspect `jj st` and `jj diff --stat`; preserve unrelated changes.163. Re-check current official documentation before changing a library, Neovim17 API, GitHub Action, or compatibility claim. Do not assume versions in this18 skill are the latest.194. Apply the required shell-command wrapper from higher-level instructions to20 every command.2122## Manage the compatibility contract2324- Keep Rust/Cargo 1.97, Edition 2024, and Neovim 0.9 as the default minimum25 versions.26- Allow an explicit compatibility or architecture change requested by the27 user. Update the manifest, runtime guards, README claims, CI coverage, and28 regression tests together; do not leave the old contract implied elsewhere.29- Distinguish a current implementation pattern from an invariant. A redesign30 may replace the implementation guidance below when it preserves the native31 ABI, command safety, lifecycle guarantees, and declared compatibility with32 equivalent tests.33- Treat the native ABI and mlua module mode as strong defaults, not absolute34 prohibitions. Change either only when the user explicitly requests that35 boundary, and include a loader/build migration plus cross-platform tests.3637## Preserve native and command-safety invariants3839### Rust and native module4041- Keep `rust-version = "1.97"` and Edition 2024 unless compatibility is being42 changed intentionally. Keep `Cargo.lock` synchronized and use `--locked` in43 reproducible build and CI commands.44- Keep `mlua` in `module` mode. Neovim supplies the Lua symbols at runtime; do45 not add a `build.rs`, pkg-config lookup, or direct Lua/LuaJIT library link.46- Keep `unsafe_op_in_unsafe_fn` and `clippy::undocumented_unsafe_blocks`47 denied in `Cargo.toml`. Document the proof obligation for any necessary48 unsafe block. Add other Clippy lints individually; do not enable the complete49 `pedantic` or `restriction` groups.50- Preserve the macOS dynamic-lookup flags in `.cargo/config.toml`. Do not set a51 workflow-level `RUSTFLAGS`, because it overrides target rustflags from Cargo52 configuration.53- Treat `luajit` and `lua51` as mutually exclusive. Never validate with54 `--all-features`; run each feature configuration separately.55- Enable only the Tokio features used by the source.56- Spawn Cargo without a shell. Keep user arguments as `Vec<String>`/Lua lists.57- Terminate Cargo and its descendants as one process group on Unix and one Job58 Object on Windows. Await/reap the worker and retain a deterministic59 long-running cancellation test.6061### Lua and Neovim6263- While retaining Neovim 0.9 compatibility, guard APIs introduced or changed in64 later versions. The current implementation preserves the `vim.validate`65 compatibility path and uses `jobstart(..., { term = true })` only on Neovim66 0.11+, with `termopen` for 0.9/0.10.67- Keep `setup()` idempotent. Clear only plugin-owned commands and autocmds.68- Prefer the current named augroups, autocmd descriptions, `vim.keymap.set`,69 buffer-local Lua callbacks, and mapping descriptions.70- When preserving the current buffer lifecycle, configure plugin-owned buffers71 before setting `filetype`, then let the `FileType` event apply buffer-local72 syntax and options.73- Prefer highlight links to standard groups with `default = true` and restore74 them after `ColorScheme`.75- Use `args.fargs` and argv lists. Do not split or concatenate user input into a76 shell command.77- The current loader uses `package.loadlib` and caches the returned module.78 Test any replacement in Neovim. Do not instantiate a standalone `mlua::Lua`79 in Rust tests: module mode deliberately leaves host Lua symbols unresolved.8081### CI and release8283- Pin third-party GitHub Actions to immutable commit SHAs, disable checkout84 credentials when unused, set minimal permissions, and keep timeouts.85- Keep Rust checks for the minimum toolchain and stable. Run tests/builds on86 Linux, macOS, and Windows; run headless Neovim integration on supported CI87 hosts where Neovim is installed.88- Run Clippy and tests for the mutually exclusive `luajit` and `lua51`89 configurations separately.90- Keep the Linux integration leg pinned to Neovim 0.9.5 and exercise a current91 Neovim release on macOS.92- Keep workflow path filters synchronized with every file class a job validates.93 In particular, Rust integration coverage must react to both `lua/` and94 `plugin/` runtime changes.95- Run headless integration as96 `nvim --headless -u NONE -l tests/integration.lua`. Do not use97 `+lua dofile(...)`, which can hide Lua assertion failures behind a successful98 process exit.99- For a version bump, update both the package version in `Cargo.toml` and the100 root package entry in `Cargo.lock`. Do not create a tag or release unless the101 user explicitly requests it.102103## Validate changes104105Run the relevant subset while iterating, then run the full local suite before106publishing. The following are logical commands; prefix each one with the active107shell wrapper required by higher-level instructions:108109```bash110cargo fmt --all -- --check111cargo clippy --locked --all-targets -- -D warnings112cargo clippy --locked --all-targets --no-default-features --features lua51 -- -D warnings113cargo test --locked114cargo +1.97.0 check --locked115cargo +1.97.0 check --locked --no-default-features --features lua51116cargo check --locked --no-default-features --features lua51117cargo test --locked --no-default-features --features lua51118cargo build --locked --release119stylua --check lua plugin tests120luacheck lua plugin tests121busted tests/command_spec.lua122nvim --headless -u NONE -l tests/integration.lua123actionlint .github/workflows/*.yml124git diff --cached --check125git diff --check126```127128Treat the explicit Rust 1.97 check as required MSRV evidence. If that toolchain129is unavailable locally, require the CI MSRV job and report the local skip.130131Record `nvim --version`. Run integration on Neovim 0.9 when that executable is132available. A newer-Neovim pass does not prove the minimum; when 0.9 is not133available locally, require the pinned Linux CI result as minimum-version134evidence.135136On macOS, inspect the release artifact when native linking changes:137138```bash139otool -L target/release/libcargo_nvim.dylib140```141142Confirm that it does not link a Homebrew or system Lua/LuaJIT library.143144Run `tests/command_spec.lua` with Busted when the local Lua installation is145healthy. The headless integration must still cover the command helper and the146actual native module in Neovim's LuaJIT host.147148## Complete the task149150- Reinspect `jj st`, the final diff, version metadata, and generated files.151- Report each command actually run and its observed result. Identify skipped152 platform checks explicitly.153- When asked to publish, use the repository's jj publishing skill. Confirm the154 final `main`/`main@origin` hash. Derive expected workflows from the changed155 paths and each workflow's path filters, then wait for those runs. If an156 expected run is absent, report it; do not manually dispatch a workflow unless157 the user authorized that external action.