As it is getting very common to receive LLM generated pull requests on the repository. It is probably better to meet these tools where they are instead of instructing the PR owner everytime.
To do this, there is a pseudo-standard way to front-load the context to these agents that is an AGENTS file and in specific case of Claude Code, the file CLAUDE.md . My proposal is that we add these files to the repository to at least get the basics right in the LLM context.
I don’t have too much of an opinion on the content but this is what I came up with after recursing with Claude Code itself.
# CLAUDE.md
This file is for Claude Code and other Claude-based AI assistants.
**You must read [AGENTS.md](AGENTS.md) before making any changes to this repository.** It contains essential development guidelines, build instructions, testing procedures, and contribution rules.
and some long file (see contributing guidelines)
# AGENTS.md - Guide for AI-Assisted Development
This document provides guidance for AI assistants (Claude, etc.) working on the SciPy codebase.
## Project Overview
SciPy is a fundamental library for scientific computing in Python, providing algorithms for optimization, integration, interpolation, eigenvalue problems, algebraic equations, differential equations, statistics, and many other domains.
- **License**: BSD-3-Clause
- **Python**: >= 3.12
- **NumPy**: >= 2.0.0
- **Repository**: https://github.com/scipy/scipy
- **Documentation**: https://docs.scipy.org/doc/scipy/
## Build System
SciPy uses **Meson** as its build system with **meson-python** as the build backend.
### Quick Build Commands
```bash
# Build the package (recommended way)
spin build
# Build with debug symbols
spin build --debug
# Build release version
spin build --release
# Build with AddressSanitizer
spin build --asan
# Build with specific BLAS
spin build --with-scipy-openblas # Use scipy-openblas32
spin build --with-accelerate # Use Apple Accelerate (macOS)
```
### Build Dependencies
- `meson-python>=0.15.0`
- `Cython>=3.0.8`
- `pybind11>=2.13.2`
- `pythran>=0.14.0`
- `numpy>=2.0.0`
- C/C++ compilers (GCC >= 9.1, Clang >= 15.0, or MSVC >= 19.20)
### Development Environment Setup
**Option 1: Pixi (Recommended)**
Pixi provides isolated, reproducible environments with pre-configured tasks:
```bash
# Build SciPy
pixi run build
# Run tests
pixi run test
# Build documentation
pixi run docs
# Run linter
pixi run lint
# Start IPython with SciPy
pixi run ipython
# Run benchmarks
pixi run bench
# Debug build
pixi run build-debug
```
Available pixi environments include: `build`, `test`, `docs`, `lint`, `bench`, `ipython`, `gdb`, `lldb`, and various array API backend environments (`jax-cpu`, `torch-cpu`, `cupy`, etc.).
**Option 2: Conda/Mamba**
```bash
conda env create -f environment.yml
conda activate scipy-dev
```
Then use `spin` commands for development tasks:
```bash
spin build # Build SciPy
spin test # Run tests
spin test -s linalg # Test specific submodule
spin docs # Build documentation
spin lint # Run linter
spin ipython # IPython with built SciPy
spin bench # Run benchmarks
```
**Option 3: Pip with virtual environment**
```bash
python -m venv venv
source venv/bin/activate
pip install -e . -v --no-build-isolation
```
## Project Structure
```
scipy/
├── cluster/ # Clustering algorithms (k-means, hierarchical)
├── constants/ # Physical and mathematical constants
├── datasets/ # Dataset registry and downloading
├── differentiate/ # Numerical differentiation
├── fft/ # Fast Fourier Transform (modern API)
├── fftpack/ # FFT (legacy API, backwards compatibility)
├── integrate/ # Numerical integration (quadrature, ODE, BVP)
├── interpolate/ # Interpolation (splines, RBF)
├── io/ # File I/O (MATLAB, NetCDF, WAV, ARFF)
├── linalg/ # Linear algebra (BLAS, LAPACK wrappers)
├── ndimage/ # N-dimensional image processing
├── odr/ # Orthogonal distance regression
├── optimize/ # Optimization and root finding
├── signal/ # Signal processing
├── sparse/ # Sparse matrices and algorithms
├── spatial/ # Spatial algorithms (KDTree, distance, transforms)
├── special/ # Special mathematical functions
├── stats/ # Statistical functions and distributions
├── _lib/ # Internal utilities and vendored code
├── _build_utils/ # Build-time utilities
└── _external/ # Minimal external code
```
Each subpackage typically contains:
- `__init__.py` - Public API exports
- Implementation files (`.py`, `.pyx`, `.pxd`, `.c`, `.cpp`)
- `tests/` directory with pytest tests
- `meson.build` - Build configuration
## Testing
### Running Tests
```bash
# Run all tests (excludes slow tests by default)
spin test
# Run tests for a specific submodule
spin test -s linalg
# Run tests on a directory or file
spin test scipy/linalg
spin test scipy/linalg/tests/test_basic.py
# Run specific test module, class, or function
spin test -t scipy.linalg.tests.test_basic
spin test -t scipy.linalg.tests.test_basic::TestClassName
spin test -t scipy.linalg.tests.test_basic::TestClassName::test_method
# Run the full test suite (including slow tests)
spin test -m full
# Run tests matching a pattern
spin test -- -k "geometric"
spin test -- -k "geometric and not rgeometric"
# Run tests in parallel
spin test -j auto
# Show timing for slowest tests
spin test -d 10
```
### Test Markers
- `@pytest.mark.slow` - Slow tests (skipped by default in some CI)
- `@pytest.mark.xslow` - Extremely slow tests (not run unless explicitly requested)
- `@pytest.mark.xfail_on_32bit` - Expected failures on 32-bit platforms
- `@pytest.mark.skip_xp_backends(...)` - Skip for specific array API backends
- `@pytest.mark.thread_unsafe` - Must run single-threaded
### Test Configuration
- Config file: `pytest.ini`
- Root conftest: `scipy/conftest.py`
- Excluded from testing: `doc`, `tools`, vendored code in `_lib/`
## Code Style
### Style Rules
- **Line length**: 88 characters (not PEP8's 79)
- **Indentation**: 4 spaces (no tabs)
- **Import convention**: `import numpy as np` (enforced)
- **Docstrings**: NumPy style
- **File endings**: POSIX (LF, not CRLF)
### Linting
```bash
# Run linter
spin lint
# Or directly with ruff
python -m ruff check --config=tools/lint.toml scipy/
```
### Ruff Configuration (tools/lint.toml)
Enabled checks:
- `E`, `F` - Pyflakes and pycodestyle
- `UP` - PyUpgrade
- `PGH004` - Blanket noqa forbidden
- `B006`, `B008` - Mutable defaults forbidden
- `B028` - Warnings must include stacklevel
- `ICN001` - Import conventions (numpy as np)
- `W292` - Newline at end of file
### Type Checking
```bash
spin mypy
```
Type checking is selective - see `mypy.ini` for configured modules.
### Pre-commit Hook
```bash
# Install the pre-commit hook
cp tools/pre-commit-hook.py .git/hooks/pre-commit
# Run manually with auto-fix
./tools/pre-commit-hook.py --fix
```
## Documentation
### Building Docs
```bash
# Build documentation
spin docs
# Quick smoke test
spin smoke-docs
# Check reference guide
spin refguide-check
```
### Docstring Format
Use NumPy docstring style:
```python
def my_function(x, y, method='default'):
"""Short one-line summary.
Longer description if needed, explaining the function's
purpose and behavior.
Parameters
----------
x : array_like
Description of x.
y : float
Description of y.
method : {'default', 'alternative'}, optional
Description of method. Default is 'default'.
Returns
-------
result : ndarray
Description of return value.
Examples
--------
>>> from scipy.subpackage import my_function
>>> my_function([1, 2, 3], 0.5)
array([...])
See Also
--------
related_function : Brief description.
Notes
-----
Implementation notes, references, etc.
References
----------
.. [1] Author, "Title", Journal, year.
"""
```
## Contributing Guidelines
### PR Requirements
1. **Unit tests** - All new code must have tests
2. **Documentation** - Docstrings with parameters, returns, examples
3. **Code style** - Pass `spin lint`
4. **Benchmarks** - For performance-critical code (use ASV)
5. **License** - Code must be BSD-compatible
### API Design
- Public API: `scipy.subpackage.function_name`
- Private functions: leading underscore `_function_name`
- All public items must be in `__all__`
- Public items imported in `__init__.py`
### Important Notes
- **Discuss first**: New features should be discussed on the [SciPy forum](https://discuss.scientific-python.org/c/contributor/scipy) before implementation
- **No style-only PRs**: Don't submit PRs that only fix PEP8 issues
- **BSD license**: All contributed code must be BSD-compatible (no GPL, Apache, or unclear licenses)
- **Backwards compatibility**: Breaking changes require deprecation cycles
## Out-of-Scope Changes
**Do not submit PRs for the following types of changes:**
### Vendored and External Code
The following directories contain vendored third-party code that is maintained upstream. Do not modify these files - instead, report issues or submit fixes to the original projects:
- `scipy/_lib/array_api_compat/` - Vendored from [array-api-compat](https://github.com/data-apis/array-api-compat)
- `scipy/_lib/array_api_extra/` - Vendored from [array-api-extra](https://github.com/data-apis/array-api-extra)
- `scipy/_lib/cobyqa/` - Vendored from [COBYQA](https://github.com/cobyqa/cobyqa)
- `scipy/_lib/pyprima/` - Vendored from [PyPrima](https://github.com/pyprima/pyprima)
- `scipy/_lib/highs/` - Vendored from [HiGHS](https://github.com/ERGO-Code/HiGHS)
- `scipy/_external/` - External code with separate maintenance
- `subprojects/` - Meson subprojects (vendored dependencies)
### Low-Value Changes
The following types of PRs create review burden without meaningful improvement:
- **Style-only fixes**: PRs that only fix PEP8/linting issues without functional changes
- **Typo fixes in comments**: Minor typo corrections in code comments (documentation typos may be acceptable)
- **Reformatting code**: Changing code layout without functional benefit
- **Adding type hints to untyped code**: Unless part of a larger coordinated effort
- **Speculative refactoring**: Restructuring code without clear benefit or prior discussion
- **"Cleanup" PRs**: Broad changes labeled as cleanup without specific justification
- **Static analysis findings**: Issues flagged by static analysis tools (e.g., "possible None dereference", "unreachable code") without demonstrating a real bug via a reproducible test case. Many such findings are false positives or impossible to trigger in practice.
### When in Doubt
If you're unsure whether a change is appropriate:
1. Check if the code is in a vendored directory (see above)
2. Ask on the [SciPy forum](https://discuss.scientific-python.org/c/contributor/scipy) before starting work
3. For bug fixes, ensure you can reproduce the issue and write a failing test first
## Common Development Tasks
### Adding a New Function
1. Implement in appropriate subpackage file
2. Add to `__all__` in that file
3. Import in `__init__.py`
4. Add comprehensive tests in `tests/`
5. Add docstring with examples
6. Update `meson.build` if adding new files
### Debugging
```bash
# Run with GDB
spin gdb
# Run with LLDB
spin lldb
# Python REPL with built scipy
spin python
# IPython REPL
spin ipython
```
### Benchmarking
```bash
# Run benchmarks
spin bench
# Compare against another branch
spin bench --compare main
```
Benchmarks use [ASV (Airspeed Velocity)](https://asv.readthedocs.io/) and are located in `benchmarks/`.
## CI/CD
GitHub Actions workflows in `.github/workflows/`:
- `linux.yml` - Main Linux testing
- `macos.yml` - macOS testing
- `windows.yml` - Windows testing
- `lint.yml` - Linting checks
- `wheels.yml` - Wheel building
- `array_api.yml` - Array API compatibility
### Commit Message Prefixes
Commit messages must start with a standard prefix indicating the type of change:
| Prefix | Description |
|--------|-------------|
| `API:` | Incompatible API change |
| `BENCH:` | Changes to benchmark suite |
| `BLD:` | Build system changes |
| `BUG:` | Bug fix |
| `DEP:` | Deprecation or removal of deprecated features |
| `DEV:` | Development tool or utility |
| `DOC:` | Documentation |
| `ENH:` | Enhancement (new feature) |
| `MAINT:` | Maintenance (refactoring, typos, etc.) |
| `REV:` | Revert an earlier commit |
| `STY:` | Style fix (whitespace, PEP8) |
| `TST:` | Test additions or modifications |
| `REL:` | Release-related |
**Format:** `PREFIX: scope: short description`
Examples:
```
ENH: stats: add new statistical test for normality
BUG: sparse.linalg.gmres: add early exit when x0 already solves problem
MAINT/TST: fft: remove xp backend skips, test fftfreq device
DOC: optimize: fix typo in minimize docstring
```
Multiple prefixes can be combined (e.g., `MAINT/TST:`). Keep the first line under 72 characters.
### Commit Message Tags for CI Control
SciPy's CI is resource-intensive. Use commit message tags to skip unnecessary workflows:
| Tag | Effect |
|-----|--------|
| `[docs only]` | Skip build/test workflows, run only documentation CI |
| `[lint only]` | Skip build/test workflows, run only linting CI |
**Example commit messages:**
```
DOC: fix typo in optimize tutorial [docs only]
STY: fix ruff warnings in stats module [lint only]
```
**When to use these tags:**
- `[docs only]` - Changes exclusively to `.rst`, `.md` files, or docstrings with no code changes
- `[lint only]` - Pure style/formatting fixes with no functional changes
**Important:** Only use these tags when you are certain your changes don't affect code behavior. If in doubt, let the full CI run.
## Key Files Reference
| File | Purpose |
|------|---------|
| `pyproject.toml` | Project metadata and dependencies |
| `meson.build` | Root build configuration |
| `scipy/meson.build` | Main package build config |
| `pytest.ini` | Pytest configuration |
| `scipy/conftest.py` | Pytest fixtures and markers |
| `tools/lint.toml` | Ruff linter configuration |
| `mypy.ini` | Type checking configuration |
| `environment.yml` | Conda environment definition |
| `pixi.toml` | Pixi environment and task definitions |
| `.spin/cmds.py` | Spin CLI commands |
## Compiled Code
SciPy contains significant amounts of compiled code:
- **Cython** (`.pyx`, `.pxd`) - Python-like syntax compiled to C
- **C/C++** - Direct implementations, especially in `special/`, `sparse/`
- **Pythran** - Python to C++ transpilation for numeric code
When modifying compiled code:
1. Rebuild with `spin build`
2. Use `spin build --debug` for debugging
3. Check for memory issues with `spin build --asan`
## Useful Links
- [SciPy Documentation](https://docs.scipy.org/doc/scipy/)
- [Development Guide](https://docs.scipy.org/doc/scipy/dev/)
- [Contributing Guide](https://docs.scipy.org/doc/scipy/dev/hacking.html)
- [SciPy Forum](https://discuss.scientific-python.org/c/contributor/scipy)
- [Issue Tracker](https://github.com/scipy/scipy/issues)
- [Code of Conduct](https://docs.scipy.org/doc/scipy/dev/conduct/code_of_conduct.html)
Unfortunately, everything in LLM world is passive and suggestive so we can’t force nothing. But this is better than nothing if someone just scans the repo for a quick-PR win. Please feel free to take this and modify it further. This is just a draft.
We can also force other major LLMs if needed, via
.cursorrules → "Read AGENTS.md"
.github/copilot-instructions.md → "Read AGENTS.md"