lumen

repository·main·Indexed 25 days ago

https://github.com/jnsahaj/lumen

A fast, terminal-based side-by-side diff viewer and code review TUI written in Rust. It supports Git and Jujutsu (jj), providing AI-powered commit message generation, change explanations, and integration with coding agents. Features include a visual diff viewer for uncommitted changes, commits, and GitHub Pull Requests, as well as an annotation system for reviewing code.

Tokens
21.4K
Snippets
26
Records
148
Agent score
82%

What's inside lumen

  1. Annotate and review diffs

    main

    Lumen allows you to add review comments at three levels of granularity:

    • Selection: Select text with the mouse and press i to annotate the range.
    • Hunk: Focus a hunk with { or } and press i to annotate the hunk.
    • File: Press i with no selection or hunk focus to annotate the entire file.

    Annotated lines are marked with a gutter indicator. Use I to view, edit, delete, copy, or export all annotations.

  2. Understand Lumen configuration precedence

    main

    Lumen applies configuration options based on a specific hierarchy. If a setting is defined in multiple places, the higher priority source wins. The order from highest to lowest priority is:

    1. CLI Flags
    2. Configuration File
    3. Environment Variables
    4. Default options

    This allows you to set global defaults via environment variables and override them on a per-project basis with a config file, or even for a single command execution using CLI flags.

    # Set global defaults in .zshrc/.bashrc
    export LUMEN_AI_PROVIDER="openai"
    export LUMEN_AI_MODEL="gpt-5-mini"
    export LUMEN_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
    
    # Override per project using config file
    {
      "provider": "ollama",
      "model": "llama3.2"
    }
    
    # Or override using CLI flags
    lumen -p "ollama" -m "llama3.2" draft
  3. Integrate lumen with coding agents

    main

    Lumen can be used as a review surface for coding agents (like Claude Code or Codex). The agent can shell-escape to lumen, allow you to annotate the diff, and then receive your annotations back via stdout.

    Workflow:

    1. Agent finishes turn.
    2. Agent runs !lumen diff (or similar shell command).
    3. User annotates the diff using i.
    4. User presses s to confirm.
    5. Lumen exits and writes formatted annotations to stdout.
    6. Agent receives the annotations and applies fixes.
    agent finishes turn → !lumen diff → annotate → press `s`
    → stdout returns to the agent → agent fixes your notes
  4. Configure AI features

    main

    To use AI helpers (commit messages, explanations, etc.), you must configure a provider and API key. Run the interactive setup command:

    lumen configure

    Settings are saved to ~/.config/lumen/lumen.config.json.

    lumen configure
  5. Use the visual diff viewer

    main

    Launch an interactive side-by-side diff viewer in your terminal. Lumen supports viewing uncommitted changes, specific commits, branch differences, and GitHub Pull Requests.

    Common Commands

    • Uncommitted changes: lumen diff
    • Specific commit: lumen diff <commit_hash>
    • Between branches: lumen diff <branch_a>..<branch_b>
    • GitHub Pull Request: lumen diff --pr <pr_number> or lumen diff <url>
    • Detect PR from current branch: lumen diff --detect-pr
    • Filter by files: lumen diff --file <path>
    • Watch mode: lumen diff --watch (auto-refreshes on file changes)
    • Stacked mode: lumen diff <range> --stacked (reviews commits one by one)
    • Soft-wrap: lumen diff --wrap
    # View uncommitted changes
    lumen diff
    
    # View changes for a specific commit
    lumen diff HEAD~1
    
    # View changes between branches
    lumen diff main..feature/A
    
    # View changes in a GitHub Pull Request
    lumen diff --pr 123
    lumen diff https://github.com/owner/repo/pull/123
    
    # Open the PR associated with the current branch
    lumen diff --detect-pr
    
    # Filter to specific files
    lumen diff --file src/main.rs --file src/lib.rs
    
    # Watch mode - auto-refresh on file changes
    lumen diff --watch
    
    # Stacked mode - review commits one by one
    lumen diff main..feature --stacked
    
    # Jump to a specific file on open
    lumen diff --focus src/main.rs
    
    # Soft-wrap long lines
    lumen diff --wrap
  6. Install lumen

    main

    You can install lumen using Homebrew (macOS/Linux) or Cargo (Rust package manager).

    Prerequisites

    • git must be installed on your system.
    • fzf (optional): Required for the lumen explain --list command.
    • mdcat (optional): Required for pretty output formatting.
    # Using Homebrew
    brew install jnsahaj/lumen/lumen
    
    # Using Cargo
    cargo install lumen
  7. Manage text selection in the diff viewer

    main

    The Selection struct tracks how a user has selected text within a diff panel. It supports two primary modes:

    • SelectionMode::Character: Selecting specific characters/columns.
    • SelectionMode::Line: Selecting entire lines.

    Key properties:

    • panel: The DiffPanelFocus where the selection resides (Old or New).
    • anchor: The starting CursorPosition.
    • head: The current end of the selection.
    • mode: The SelectionMode used.

    Useful methods:

    • .is_active(): Returns true if a selection is currently active.
    • .contains(line, column): Checks if a specific coordinate is within the selection.
    • .is_line_fully_selected(line): Checks if an entire line is included in the selection.
    • .normalized_range(): Returns the selection as a (start, end) tuple where start <= end.
  8. Mouse interactions in the Lumen TUI

    main

    The Lumen TUI supports various mouse interactions to navigate the diff viewer and sidebar:

    • Sidebar: Click on files or directories in the sidebar to select them or toggle directory views. Clicking the sidebar clears any current text selection.
    • Diff View Selection:
      • Click: Click in the gutter to select a whole line, or click in the content area to select specific characters. This clears previous selections.
      • Drag: Click and drag to extend a text selection.
    • Scrolling:
      • Vertical Scroll: Use the mouse wheel to scroll the sidebar or the diff content independently.
      • Horizontal Scroll: Use horizontal scroll events to move through wide diffs.

    Special Interactions

    • Stacked Mode: In stacked commit mode, click the arrows (< or >) in the header to navigate between commits.
    • Annotation Overlays: Click on an annotation overlay to trigger the inline editor.
  9. How FileHighlighter works

    main

    FileHighlighter is a high-level abstraction for syntax highlighting that handles the complexity of mapping byte-offset highlights from tree-sitter to human-readable line numbers.

    It works by:

    1. Loading the appropriate LanguageConfig based on the file extension.
    2. Running the tree-sitter highlighter over the entire content.
    3. Mapping the resulting byte offsets to 1-based line numbers.
    4. Storing these in a HashMap where the key is the line number and the value is a list of text segments and their associated highlight indices.
  10. Use the Modal UI system for diff views

    main

    The Modal struct is used to present various interactive overlays within the Lumen diff view. Depending on the ModalContent variant, the modal can display information, request confirmation, pick files, show keybindings, manage annotations, or perform a global search.

    Each modal type has specific constructor methods to initialize its content and state.

  11. Convert Git syntax to Jujutsu (jj) syntax

    main

    The JjBackend implementation includes logic to detect common Git-style references and suggest their Jujutsu equivalents to prevent errors.

    Git SyntaxJujutsu (jj) Suggestion
    HEAD@-
    HEAD~N or HEAD^N@<N+1> (e.g., HEAD~1 becomes @--)
    HEAD~ or HEAD^@--
  12. Manage code annotations in Lumen

    main

    Lumen allows users to add notes to code changes during a review via Annotation objects. Annotations can be attached to an entire file or to a specific range of lines on either the 'old' (left) or 'new' (right) panel.

    Annotation Targets

    • AnnotationTarget::File: Applies to the whole file.
    • AnnotationTarget::LineRange: Applies to a specific range of lines on a specific DiffPanelFocus (Old or New).

    Managing Annotations via AppState

    You can manage the lifecycle of annotations using the following AppState methods:

    • add_annotation(filename, target, content, created_at): Creates a new annotation and returns its unique u64 ID.
    • update_annotation(id, content): Updates the text content of an existing annotation.
    • remove_annotation(id): Deletes an annotation by its ID.
    • get_annotation_by_id(id): Retrieves an annotation reference.
    • format_annotations_for_export(): Generates a string formatted in a GitHub Pull Request review comment style, including file paths, line numbers, and side (LEFT/RIGHT) references.