Skip to main content

tree-sitter-logrotate

tree-sitter-logrotate parses logrotate configuration and state files with Tree-sitter. The configuration grammar recognizes global directives, rotation stanzas, path lists, comments, includes, quoted arguments, and all five raw script blocks. The state grammar recognizes version 1 and version 2 headers, quoted paths, and timestamps. Script text is preserved as script_body and is never executed.

The committed parser uses Tree-sitter language ABI 15. The reviewed syntax baseline is logrotate revision 3be1e9ccffe0c2245ed596183c74913d553f9f18, which includes the logrotate 3.22 syntax reviewed for the first release.

The user and integration documentation covers package setup, syntax trees, portable queries, editor setup, and compatibility.

Consumers

The repository publishes both generated parsers through C source, npm, PyPI, crates.io, Maven Central, Go, Swift Package Manager, Zig, and standalone WASM artifacts. Configuration highlight, shell-injection, and fold queries live in queries/; the state highlight query lives in src/state/queries/.

The editor setup guide covers Neovim, Helix, and Zed. Each setup pins both parsers and their queries to one grammar revision.

Neovim

Neovim 0.12.0 or newer, the current main branch of nvim-treesitter, the Tree-sitter CLI, and a C compiler are required. Native vim.pack users can add both packages in init.lua:

Native vim.pack

vim.api.nvim_create_autocmd("PackChanged", {
  callback = function(event)
    local name, kind = event.data.spec.name, event.data.kind
    if name == "tree-sitter-logrotate" and (kind == "install" or kind == "update") then
      vim.cmd.source(vim.fs.joinpath(event.data.path, "build.lua"))
    end
  end,
})

vim.pack.add({
  {
    src = "https://github.com/nvim-treesitter/nvim-treesitter",
    version = "main",
  },
}, { load = true })

vim.pack.add({
  {
    src = "https://github.com/willibrandon/tree-sitter-logrotate",
    version = vim.version.range("0.2"),
  },
}, { load = true })

LazyVim

Create lua/plugins/logrotate.lua:

return {
  {
    "willibrandon/tree-sitter-logrotate",
    version = "*",
    dependencies = { "nvim-treesitter/nvim-treesitter" },
  },
}

Both installations compile the configuration and state parsers plus the Bash parser used inside script blocks. Run :checkhealth tree-sitter-logrotate after restarting Neovim.

Usage

Open logrotate.conf, a direct child of logrotate.d, *.logrotate, *.logrotate.conf, logrotate.status, or logrotate/status. The plugin also recognizes complete first-line stanzas, state headers, and files reached through an include from an open configuration.

Configuration buffers provide Tree-sitter highlighting, Bash highlighting inside all five script blocks, indentation, folding, # comments, % matching between script directives and endscript, and directive completion. Use CTRL-X CTRL-O for built-in completion. LazyVim's Blink completion uses the same source automatically; use CTRL-Y to accept a selected directive and Enter to insert an indented newline.

Use :LogrotateInstall, :LogrotateUpdate, and :LogrotateUninstall to manage the two parsers. Use :checkhealth tree-sitter-logrotate to verify the complete installation.

Local development

The development container is the reference environment. It pins every toolchain, does not forward host credentials, and keeps platform-specific output in named volumes.

For a native checkout, install the versions in toolchains.json, then run:

nvm use
npm install --global npm@12.0.2
npm ci
npm run verify
npm run test:bindings
npm run test:wasm
npm run test:fixtures
npm run test:sanitizers
npm run test:performance
npm run test:neovim:install

Run npm run generate after changing grammar.js. Generated parser files are committed and must pass npm run check:generated. TREE_SITTER_BUILD_DIR relocates native and WASM output; its default is the ignored build directory.

More native setup details are in docs/native-development.md.

The documentation site has a separate locked dependency tree. Its local development and preview commands are described in docs/documentation-site.md.

Binding examples

Every example parses supplied text. None reads a configuration from disk or starts logrotate.

C

#include <string.h>
#include <tree_sitter/api.h>
#include <tree_sitter/tree-sitter-logrotate.h>

const char *source = "/var/log/app.log {\n  rotate 7\n}\n";
TSParser *parser = ts_parser_new();
ts_parser_set_language(parser, tree_sitter_logrotate());
TSTree *config = ts_parser_parse_string(parser, NULL, source, strlen(source));

const char *state_source =
    "logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n";
ts_parser_set_language(parser, tree_sitter_logrotate_state());
TSTree *state = ts_parser_parse_string(
    parser, NULL, state_source, strlen(state_source));

ts_tree_delete(config);
ts_tree_delete(state);
ts_parser_delete(parser);

Node.js

import Parser from "tree-sitter";
import Logrotate, { stateLanguage } from "tree-sitter-logrotate";

const parser = new Parser();
parser.setLanguage(Logrotate);
const tree = parser.parse("/var/log/app.log {\n  rotate 7\n}\n");
console.log(tree.rootNode.toString());

parser.setLanguage(stateLanguage);
const stateTree = parser.parse(
  'logrotate state -- version 2\n"/var/log/app.log" 2026-8-14-12:30:45\n',
);
console.log(stateTree.rootNode.toString());

Python

from tree_sitter import Language, Parser
from tree_sitter_logrotate import language, state_language

parser = Parser(Language(language()))
tree = parser.parse(b"/var/log/app.log {\n  rotate 7\n}\n")
print(tree.root_node)

parser.language = Language(state_language())
state_tree = parser.parse(
    b'logrotate state -- version 2\n"/var/log/app.log" 2026-8-14-12:30:45\n'
)
print(state_tree.root_node)

Rust

let mut parser = tree_sitter::Parser::new();
parser
    .set_language(&tree_sitter_logrotate::LANGUAGE.into())
    .expect("load logrotate grammar");
let tree = parser
    .parse("/var/log/app.log {\n  rotate 7\n}\n", None)
    .expect("parse logrotate configuration");
println!("{}", tree.root_node());

parser
    .set_language(&tree_sitter_logrotate::STATE_LANGUAGE.into())
    .expect("load logrotate state grammar");
let state_tree = parser
    .parse(
        "logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n",
        None,
    )
    .expect("parse logrotate state");
println!("{}", state_tree.root_node());

Go

language := sitter.NewLanguage(logrotate.Language())
parser := sitter.NewParser()
defer parser.Close()
if err := parser.SetLanguage(language); err != nil {
	panic(err)
}
tree := parser.Parse([]byte("/var/log/app.log {\n  rotate 7\n}\n"), nil)
defer tree.Close()

if err := parser.SetLanguage(sitter.NewLanguage(logrotate.StateLanguage())); err != nil {
	panic(err)
}
stateTree := parser.Parse([]byte(
	"logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n",
), nil)
defer stateTree.Close()

The imports are github.com/tree-sitter/go-tree-sitter as sitter and github.com/willibrandon/tree-sitter-logrotate/bindings/go as logrotate.

Java

var language = new Language(Objects.requireNonNull(TreeSitterLogrotate.language()));
try (var parser = new Parser(language);
     var tree = parser.parse("/var/log/app.log {\n  rotate 7\n}\n").orElseThrow()) {
    System.out.println(tree.getRootNode().toSexp());
}

var stateLanguage =
    new Language(Objects.requireNonNull(TreeSitterLogrotate.stateLanguage()));
try (var parser = new Parser(stateLanguage);
     var tree = parser.parse(
         "logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n"
     ).orElseThrow()) {
    System.out.println(tree.getRootNode().toSexp());
}

The Maven coordinates are io.github.willibrandon:jtreesitter-logrotate. Java applications also need JTreeSitter 0.26 and its compatible native Tree-sitter runtime. The grammar artifact includes the platform grammar library; it does not replace the Tree-sitter runtime used by JTreeSitter.

Swift

let parser = Parser()
try parser.setLanguage(Language(language: tree_sitter_logrotate()))
let tree = parser.parse("/var/log/app.log {\n  rotate 7\n}\n")
print(tree?.rootNode as Any)

try parser.setLanguage(Language(language: tree_sitter_logrotate_state()))
let stateTree = parser.parse(
    "logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n"
)
print(stateTree?.rootNode as Any)

Zig

const parser = Parser.create();
defer parser.destroy();
const language = Language.fromRaw(logrotate.language());
defer language.destroy();
try parser.setLanguage(language);
const tree = parser.parseString("/var/log/app.log {\n  rotate 7\n}\n", null).?;
defer tree.destroy();

const state_language = Language.fromRaw(logrotate.stateLanguage());
defer state_language.destroy();
try parser.setLanguage(state_language);
const state_tree = parser.parseString(
    "logrotate state -- version 2\n\"/var/log/app.log\" 2026-8-14-12:30:45\n",
    null,
).?;
defer state_tree.destroy();

Browser WASM

import { Language, Parser } from "web-tree-sitter";

await Parser.init({ locateFile: () => "/web-tree-sitter.wasm" });
const language = await Language.load("/tree-sitter-logrotate.wasm");
const parser = new Parser();
parser.setLanguage(language);
const tree = parser.parse("/var/log/app.log {\n  rotate 7\n}\n");
console.log(tree.rootNode.toString());

const stateLanguage = await Language.load("/tree-sitter-logrotate-state.wasm");
parser.setLanguage(stateLanguage);
const stateTree = parser.parse(
  'logrotate state -- version 2\n"/var/log/app.log" 2026-8-14-12:30:45\n',
);
console.log(stateTree.rootNode.toString());

State files

The state parser ships in the same packages and release. Every example above loads it from the same binding and parses a complete version 2 state record.

File names

Editor integrations should recognize these configuration names automatically:

  • logrotate.conf
  • files directly below a logrotate.d directory
  • *.logrotate
  • *.logrotate.conf

Hosts with content detection may also recognize an otherwise unclassified file when its first physical line is a complete log-path stanza. The line may contain one or more absolute or ~/ paths, including quoted or escaped paths, followed by {, optional whitespace, and an optional trailing comment. Detectors should examine no more than 8,192 characters. Generic configuration text, incomplete stanzas, shell functions, shebangs, and logrotate state files must not select this grammar.

Files resolved through an include directive from an open configuration root also use the configuration language. Existing relative, absolute, and quoted files are included, along with regular files directly enumerated from an included directory. Missing targets, nested directory entries, and unexpanded wildcard targets do not create an association.

Editor integrations should recognize these state-file names automatically:

  • logrotate.status
  • logrotate/status

An otherwise unclassified file uses the state language when its first physical line is exactly logrotate state -- version 1 or logrotate state -- version 2. Detection examines no more than 8,192 characters. Unsupported versions, extra whitespace, generic status files, and logrotate/nested/status are rejected.

The machine-readable cases are in test/fixtures/file-recognition.json.

Syntax boundary

These are syntax grammars. They do not resolve includes or globs, inspect users and groups, apply inherited settings, check filesystem permissions, validate directives against an installed logrotate version, or execute scripts. Those operations require host state and belong in a language server or another semantic tool.

An include path remains an include_directive node even when the referenced file does not exist. Unknown directives remain ordinary directive nodes so newer logrotate releases and vendor builds do not become syntax errors.

Compatibility and releases

Tree-sitter CLI 0.26.3 is the tested minimum and 0.26.12 is the pinned generation version. The Node binding uses tree-sitter 0.25.1 or later in the 0.25 line; the standalone WASM artifact uses web-tree-sitter 0.26. Releases use Semantic Versioning and treat named nodes, fields, and query captures as compatibility surfaces even before 1.0.

Each release aligns every package version, builds from committed generated source, and publishes a source archive, WASM parser, checksums, CycloneDX SBOMs, and GitHub provenance attestations. See docs/compatibility.md and docs/release.md.

License

MIT

Metadata

Release files for tree-sitter-logrotate 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tree-sitter-logrotate 0.2.1
File Size Uploaded
tree_sitter_logrotate-0.2.1.tar.gz 37.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for tree-sitter-logrotate 0.2.1
File
tree_sitter_logrotate-0.2.1-cp310-abi3-win_arm64.whl CPython 3.10 abi3 Windows ARM64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.10 abi3 Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
tree_sitter_logrotate-0.2.1-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 295.9 kB

Release files / tree_sitter_logrotate-0.2.1.tar.gz

Download URL tree_sitter_logrotate-0.2.1.tar.gz
Size 37.9 kB
Tags Source
SHA-256 checksum
How to use checksums
138a44d1e8578b395272c6bd28377ebf2ff6fe6ff77550ff03689311b40f84fc
BLAKE2b-256 checksum
How to use checksums
6958c4296c0e1283d72e5fe38fe5c773e1f96099ab7504dfbb4636c88e31a2e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-win_arm64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-win_arm64.whl
Size 27.3 kB
Tags CPython 3.10 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
d96d31b87c212bf24d4564ea7f68a1784ebfdeacc8dc7df49e9a213e8dba4768
BLAKE2b-256 checksum
How to use checksums
586695556032f1d6555743689b7127bf8b8870fb4b41630e2503a68fc2098b40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-win_amd64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-win_amd64.whl
Size 27.0 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
d719b524a711e513bb5a668f2f521168ca398e2193078236247734e22e82dcb5
BLAKE2b-256 checksum
How to use checksums
eeed8bc7740e74d4bc0e5638dc1404daec8be8f03285ba86bd46debd66f581c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl
Size 44.4 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
3d39cc8c30fa84aa51a45e3be2df713e4bf0588d0dff20849da736a5ef553287
BLAKE2b-256 checksum
How to use checksums
2dc2109854561ac9c1a52716bac75f177018f82e54f2605ad7c36c84083cfd6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl
Size 44.1 kB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
69831c94ea16f9ed0a2b590a32c6a589048b0b854f4ad6808e39f1b7fb8f5858
BLAKE2b-256 checksum
How to use checksums
4dbc59601628e842b1046dbdbe9a9ca33e0f46e30b930e81ce0fc21f43c964f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 44.4 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
a36ce534392c103dcf00acfbed17bd7404df30761a06b646d72a08374d0f1167
BLAKE2b-256 checksum
How to use checksums
958f323f33640ba88cc501ae836f5afe522b29f050740ac83697a8f824dd55f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 44.0 kB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 abi3
SHA-256 checksum
How to use checksums
4ae22bbacf45f63927dc12ef030cfc80175b2ac21b3f1edf29199d4a609cc971
BLAKE2b-256 checksum
How to use checksums
de9c5cf110d590707202e8f994db4150d96d318c9df5ff40e987d2db4ea8dba4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / tree_sitter_logrotate-0.2.1-cp310-abi3-macosx_11_0_arm64.whl

Download URL tree_sitter_logrotate-0.2.1-cp310-abi3-macosx_11_0_arm64.whl
Size 26.9 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1072ac078f897ad1b7f1458be3c01383e1dcd1c931c2338e8fe9c8d312d02e87
BLAKE2b-256 checksum
How to use checksums
7626378e635eda7c4a128245d563d50375f42f0782418bb2ccadaf4ac1133422
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

8 release files

0.2.0

8 release files

0.1.3

8 release files

0.1.2

7 release files

0.1.1

7 release files

0.1.0

7 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page