Repository navigation
Description
Is your feature request related to a problem? Please describe.
When creating custom commands that need to operate on specific lines in diffs, it would be valuable to have access to the current line number information. While lazygit already tracks line numbers internally (via pkg/gui/patch_exploring/state.go), this information is not currently exposed to custom command templates.
This would enable more precise integrations with external tools like linters, analysis tools, or other utilities that benefit from knowing the exact line context.
Describe the solution you'd like
I'd like to have access to line number information in custom command templates, such as:
customCommands:
- key: 'A'
command: 'my-tool --file={{.SelectedFile.Name}} --line={{.CurrentLineNumber}}'
context: 'files'
description: 'Run tool on current line'Specifically, I'd like template variables like:
{{.CurrentLineNumber}}- The actual line number in the original file{{.SelectedLineInDiff}}- The position in the diff view (optional)
Describe alternatives you've considered
- Parsing git diff output externally - This duplicates lazygit's existing line tracking logic and is less reliable
- Using file-level information only - This works but loses precision for line-specific operations
- External tools to analyze cursor position - More complex to implement and maintain
I noticed that lazygit already has excellent infrastructure for this in the patch exploring system (CurrentLineNumber() method), so exposing this to custom commands would leverage existing functionality.
Additional context
- Current lazygit version: 0.52.0
- Use case example: I'm building an MCP (Model Context Protocol) bridge that allows AI assistants to interact with lazygit. When implementing this, I realized that having access to line numbers from custom commands would make the integration much more precise and efficient.
- The line tracking functionality already exists in
pkg/gui/patch_exploring/state.go - This would enhance lazygit's integration capabilities while maintaining its core simplicity
The line numbers would only be populated when in applicable contexts (diff views, staging) and would be nil otherwise, maintaining backwards compatibility.
I can work on a PR if this feature request is accepted.
Activity
KennethHoff commentedon Aug 6, 2026
This comment extends #4677's original ask beyond a single-line cursor position to also expose range-selection information to custom command templates. Everything below is traced from source only, pinned to commit bd76666 on master (current release v0.64.0) — I haven't run these code paths live, only read them.
The original issue requests
{{.CurrentLineNumber}}for diff-browsing contexts like staging, which is valuable for automating line-level operations. Alongside that, the staging and patch-building panels also support visual-mode range selection (v, extendable with shift+arrow keys, or a plain mouse drag), and exposing that selection's bounds would unlock range-based commands — exactly as{{.SelectedCommitRange}}already does for ranged commit selection (PR #4204).Tracing the source, the necessary machinery already exists in the codebase, simply not wired into the custom command template system. The
SessionStatestruct (pkg/gui/services/custom_commands/session_state_loader.golines 195–213) holds the fields that become{{.SelectedX}}template variables and includesSelectedCommitRange *CommitRange(line 200), but nothing equivalent for diffs.SessionStateLoader.call()(starting line 215, body running to itsreturnat lines 240–258) populatesSessionStateentirely by reading list-based contexts — Files, Branches, Commits, etc. — and never touches the diff-browsing contexts:Staging,StagingSecondary, orCustomPatchBuilder.Those three contexts are all constructed via
NewPatchExplorerContext(...)(pkg/gui/context/setup.golines 44–74), which surfaces selection state throughPatchExplorerContext.GetState() *patch_exploring.State(pkg/gui/context/patch_explorer_context.go). TheStatetype (pkg/gui/patch_exploring/state.go) already exposes both halves of this ask:CurrentLineNumber()(lines 389–391) returns the single-cursor file line number, andSelectedViewRange()/SelectedPatchRange()(lines 353, 370) return the bounds of the current selection as(start, end)indices — these work across all select modes (line, hunk, and range), not just an active range. File line numbers are mapped from patch indices viaPatch.LineNumberOfLine(idx int)(pkg/commands/patch/patch.goline 92).One way to close this gap: add
{{.CurrentLineNumber}}(int) to satisfy the original ask, and{{.SelectedLineRange}}with.From/.Tofields (both file line numbers, as ints) mirroringSelectedCommitRange's existing.To/.Fromshape from PR #4204. When no range is active,.Fromand.Towould both equalCurrentLineNumber, matching how a single selected commit already degenerates forSelectedCommitRange. Populate these only in theStaging,StagingSecondary, andCustomPatchBuildercontexts, and leave them unset elsewhere — as the original issue already proposed for its narrower scope. The file path for these lines is already available via the existing{{.SelectedFile.Name}},{{.SelectedPath}}, or{{.SelectedCommitFilePath}}fields, so no new field is needed there.This project doesn't accept pull requests (per CONTRIBUTING.md), so this stays a discussion topic for your design rather than a code contribution.
Drafted with AI Assistance and reviewed by the reporter before posting.
nat-e commentedon Sep 1, 2026
I'm using Lazygit to review LLM changes before opening PRs and would find this super useful so that I could add comments directly through lg via a custom command
jozefRudy commentedon Oct 31, 2026
Extending this to the commit-files diff view, which the staging/patch contexts above don't cover.
There,
editAtLineresolves the diff line against the worktree copy of the file (EditFileOfDiffAtLine→existingPathInWorktreeOfDiff), so external tools cannot open the file as it exists in the selected commit. A custom command could, if it knew the selected line.Minimal shape, using what already exists:
SelectedLine(1-based view line),SelectedLineContent, andSelectedFileLine(only where a mapping exists) toSessionStateinpkg/gui/services/custom_commands/session_state_loader.go, populated incall()from the focused context's view (ViewTrait.SelectedLineIdx()/SelectedLine())DiffHelper.AdjustLineNumber(path, lineIndex+1, viewName)for the file line — the same calleditAtLinealready makes+/-markers, which is why both values are usefulSelectedLineContentis what makes arbitrary revisions work without diff math: a custom command can locate that text ingit show <rev>:<path>, so hunk offsets don't matter and lazygit needs no knowledge of old files, revisions, or diff direction. It also lets line-scoped commands work outside diffs, where a file line is not tracked at all.Concrete use case: opening a file at the selected commit and its parent at the same place, side by side in an external editor.