Files
rich-print/AGENTS.md

5.5 KiB

AGENTS.md

Guidelines for agentic coding agents working in this repository.

Project Overview

rp is a Python CLI tool for rich-printing files (markdown, JSON, code, etc.) in the terminal. It uses rich for rendering and typer for the CLI interface.

  • Language: Python 3.12+
  • Package Manager: uv
  • Entry Point: rprp.cli:app
  • Source Location: src/rp/

Build/Lint/Test Commands

Setup

uv sync  # Install dependencies

Running the CLI

uv run rp <file>            # Rich-print a file
uv run rp --help            # Show help
uv run rp --version         # Show version
echo '{"a":1}' | uv run rp  # Read from stdin

Testing

This project does not yet have automated tests. When adding tests:

# Run all tests
uv run pytest

# Run a single test file
uv run pytest tests/test_detect.py

# Run a single test function
uv run pytest tests/test_detect.py::test_detect_json_from_content

# Run with verbose output
uv run pytest -v
uv run ruff check src/   # Lint
uv run ruff format src/  # Format
uv run mypy src/         # Type check

Code Style Guidelines

Imports

Order imports using standard library → third-party → local grouping:

from __future__ import annotations

import sys
from pathlib import Path
from typing import Annotated, Optional

import typer
from rich.console import Console

from rp import __version__
from rp.detect import detect_type
  • Always use from __future__ import annotations at the top for modern type hint syntax
  • Use explicit imports (no from module import *)
  • Import Path from pathlib, not os.path

Formatting

  • Line length: 88 characters (ruff default)
  • Quotes: Prefer double quotes for strings, single quotes inside f-strings if needed
  • Trailing commas: Use in multi-line collections and function arguments

Type Hints

  • Use modern union syntax: str | None instead of Optional[str]
  • Use Annotated[Type, typer.Option(...)] for CLI parameters
  • Always annotate function parameters and return types
  • Use dataclass for simple data containers
def detect_type(
    path: str | None = None,
    content: str | None = None,
    explicit_type: str | None = None,
) -> str:
    ...

Naming Conventions

  • Modules: lowercase with underscores (detect.py, render.py)
  • Classes: PascalCase (RenderOptions)
  • Functions/Variables: snake_case (detect_type, file_path)
  • Constants: UPPER_SNAKE_CASE (EXTENSION_MAP, _FILENAME_MAP)
  • Private module-level: prefix with underscore (_MARKDOWN_TYPES)
  • CLI parameter names: Avoid Python builtins (use file_type not type)

Error Handling

  • Use rich.Console for user-facing error messages with [red]Error:[/red] prefix
  • Exit with typer.Exit(code=1) for errors, typer.Exit() for success
  • Catch specific exceptions, not bare except:
try:
    content = file.read_text(encoding="utf-8")
except UnicodeDecodeError:
    console.print(f"[red]Error:[/red] Cannot read binary file: {file}")
    raise typer.Exit(code=1)
except (PermissionError, OSError) as e:
    console.print(f"[red]Error:[/red] {e}")
    raise typer.Exit(code=1)
  • For fallback behavior (e.g., unknown lexer), catch broadly but document why:
try:
    renderable = Syntax(content, file_type, ...)
except Exception:
    # Unknown lexer — fall back to plain text
    renderable = Syntax(content, "text", ...)

CLI Patterns

  • Use typer.Option() with --flag/--no-flag for boolean toggles
  • Use Annotated[Type, typer.Option(...)] for all options
  • Set no_args_is_help=False when stdin input is valid
  • Use callbacks for --version with is_eager=True

Module Structure

Each module should have:

  1. Module docstring (one line)
  2. from __future__ import annotations
  3. Standard library imports
  4. Third-party imports
  5. Local imports
  6. Constants (module-level)
  7. Classes
  8. Functions

File Type Detection

When adding new file types:

  1. Add extension to EXTENSION_MAP in detect.py
  2. Use Pygments lexer name as the value
  3. For special filenames (e.g., Dockerfile), add to _FILENAME_MAP

Rendering

  • markdown and md → use rich.markdown.Markdown
  • json → use rich.json.JSON with fallback to Syntax
  • All other types → use rich.syntax.Syntax

Project Structure

rich-viewer/
├── pyproject.toml      # Project config, dependencies, entry point
├── uv.lock             # Lockfile (commit this)
├── .gitignore
├── README.md
├── AGENTS.md           # This file
└── src/
    └── rp/
        ├── __init__.py  # Version metadata
        ├── cli.py       # Typer CLI entry point
        ├── detect.py    # File type detection
        ├── render.py    # Rendering logic
        └── py.typed     # PEP 561 marker

Dependencies

  • rich>=13.0 — Terminal rendering (Markdown, JSON, Syntax)
  • typer>=0.12 — CLI framework

Both are runtime dependencies. No dev dependencies are currently specified.

Git Conventions

  • Write clear, imperative commit messages
  • Reference issues/PRs when applicable
  • Keep commits focused (one logical change per commit)

Notes for Agents

  • This is a small, focused CLI tool — prefer simplicity over abstraction
  • The src/ layout is intentional for proper packaging
  • The py.typed marker indicates type hints are available to consumers
  • When in doubt, follow patterns from existing code in the same file