Add AGENTS.md with coding guidelines for agentic agents - Document build/lint/test commands (uv, pytest, ruff, mypy) - Specify code style: imports, formatting, type hints, naming - Outline error handling patterns and CLI conventions - Describe project structure and file type detection

This commit is contained in:
2026-04-01 16:14:51 -07:00
parent dd45fb05f7
commit e5194a7793

187
AGENTS.md Normal file
View File

@@ -0,0 +1,187 @@
# 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**: `rp``rp.cli:app`
- **Source Location**: `src/rp/`
## Build/Lint/Test Commands
### Setup
```bash
uv sync # Install dependencies
```
### Running the CLI
```bash
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:
```bash
# 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
```
### Linting & Type Checking (recommended)
```bash
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:
```python
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
```python
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:`
```python
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:
```python
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