| commit | 65fcd03527aeafd3a2efade21b3c1342eb65f489 | [log] [tgz] |
|---|---|---|
| author | Andrea Arcangeli <aarcange@redhat.com> | Thu Dec 18 18:27:51 2025 +0100 |
| committer | Andrea Arcangeli <aarcange@redhat.com> | Thu Dec 18 18:27:51 2025 +0100 |
| tree | 3583f12d25f71a8fb8200bbab42a66d378728d70 | |
| parent | d0c5d055c9dec2d8ef200095351702ac6a9758b3 [diff] |
Add GBNF grammar documentation Document the --gbnf option and GBNF grammar support in ripgrep-edit, including usage with gptel backend and its role in constraining LLM outputs to prevent snippet unification issues. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
ripgrep-edit enables razor coding by allowing LLM workflows to operate with razor-thin context, input and output.
ripgrep with configurable context linesgit clone https://gitlab.com/aarcange/ripgrep-edit.git cd ripgrep-edit cargo build --release
A Fedora Copr package is available:
sudo dnf copr enable vittyvk/ripgrep-edit sudo dnf install ripgrep-edit
The Copr is built for Fedora rawhide / 43 / 42.
-e, --regexp <REGEXP>: Regex pattern to search for-E, --editor <EDITOR>: Editor command (e.g., vim, emacs)-C, --context <N>: Number of context lines-A, --after-context <N>: Lines of context to show after each match-B, --before-context <N>: Lines of context to show before each match--require-all-files: Require all files in ripgrep output to be present in the edited file--context-separator <SEPARATOR>: Separator string between snippets--filename-prefix <PREFIX>: Prefix for filename lines-S, --smart-case: Enable smart case search-i, --ignore-case: Ignore case distinctions-w, --word-regexp: Force pattern to match only whole words-U, --multiline: Enable multiline matching--multiline-dotall: Enable dotall mode for multiline matching--sort <SORT>: Sort results by path, modified, accessed, or created time--sortr <SORT>: Sort results in reverse order by path, modified, accessed, or created time--dump-on-error: Dump processed tempfile to stderr on error--gbnf: Generate dynamic GBNF grammar filerg-edit [OPTIONS] --regexp <REGEXP> --editor <EDITOR> [PATHS...] rg-edit -e "function\s*\(" -E vim src/ rg-edit -e "function\s*\(" -E "emacsclient" -C 8 src/ rg-edit -E vim -U -e '(?s)^<<<<<<<+ .*?^>>>>>>>+ ' # resolve git conflicts
Large codebases challenge LLMs due to context limits. Traditional vibe coding tools require reading snippets of multiple large files through the LLM agentic workflow.
ripgrep-edit solves this by:
ripgrep-edit lets the programmer define the exact context needed, presenting it in a structured, linear format optimized for the LLM's key-value input. The resulting gain in efficiency enables real-time visibility into what the LLM is generating — allowing to interrupt, refine input, adjust directives, and eliminate unnecessary context, computation, and cost.
The goal is to optimize the LLM's most demanding task — writing code — by minimizing perplexity and maximizing efficiency.
This works best with tools like gptel-rewrite, where extra context can be included for more complex refactorings.
To be effective, ripgrep-edit requires a well-crafted prompt:
You are a careful programmer. Rewrite cross-file snippets. Rewrite everything exactly the same except: the required change. Keep the filenames at the start of the files. Keep the separators at the end of the snippets. Do not delete the filenames and the separators. Do not add markdown fences. Do not ask clarification.
rg-edit, rg-edit-git, rg-edit-git-conflicts functionsrg-edit-git C-c rrg-edit-git-conflicts C-u C-c r(add-to-list 'load-path "~/.../ripgrep-edit/emacs/") (use-package rg-edit :ensure nil :config (setq-default rg-edit-auto-mark-whole-buffer t) (setq-default rg-edit-executable "~/.../ripgrep-edit/target/release/rg-edit"))
ripgrep-edit leverages GBNF to constrain LLM outputs when used with llama.cpp as backend. With the --gbnf option, a *.gbnf file with the grammar is created in the same directory as the temporary rg-edit buffer. The rg-edit.el plugin automatically detects it and injects its contents into the JSON request as the grammar field if the gptel backend is defined with the gbnf capability.
(setq-default gptel-model `test gptel-backend (gptel-make-openai "test" :stream t :protocol "http" :host "localhost:8811" :models '((test :capabilities (gbnf))))
The GBNF grammar is used primarily to prevent the model from unifying close snippets by replacing the separator with code from the middle.
The GBNF grammar does not guarantee that the LLM output will pass all checks and be committed by rg-edit when the file is closed. It'd be a misfeature to correct an LLM output that has already gone astray. It is intended to provide self-restraint to the model when the edit session is otherwise going well.
If the GBNF grammar is configured to be used during inference, a notice will appear about it in the *rg-edit* buffer.
Emacs' wgrep offers similar functionality but relies on interactive edits, such as C-c C-d to delete a line, which are incompatible with the full rewrites required in LLM-driven workflows.
Unlike wgrep, ripgrep-edit is editor-agnostic and LLM-agnostic: any editor can be used, making it ideal for diverse environments, or simply to avoid opening multiple files with vim.