| name | pypi-readme-creator |
| description | When creating a README for a Python package. When preparing a package for PyPI publication. When README renders incorrectly on PyPI. When choosing between README.md and README.rst. When running twine check and seeing rendering errors. When configuring readme field in pyproject.toml. |
PyPI README Creator
Generate professional, PyPI-compliant README files in Markdown or reStructuredText that render correctly on PyPI, GitHub, GitLab, and BitBucket.
When to Use This Skill
Use this skill when:
- Creating README files for Python packages intended for PyPI publication
- Converting between Markdown and reStructuredText formats
- Validating README markup before publishing to PyPI
- Setting up
pyproject.tomlmetadata for README inclusion - Generating README.rst files from Sphinx documentation
- Ensuring README compatibility across multiple platforms (PyPI, GitHub, GitLab, BitBucket)
- Troubleshooting README rendering issues on PyPI
- Creating documentation that balances technical accuracy with user accessibility
Core Capabilities
Supported Formats
PyPI's README renderer supports three formats with specific constraints:
Plain Text (
text/plain)- Use for minimal documentation
- No formatting capabilities
- Renders exactly as written
reStructuredText (
text/x-rst)- Rich formatting with directives and roles
- Critical limitation: Sphinx extensions NOT allowed on PyPI
- No
:py:func:,:ref:,:doc:, or other Sphinx-specific roles - Standard docutils directives only (admonitions, code blocks, tables)
- Use
sphinx-readmeextension to generate PyPI-compatible RST from Sphinx docs
Markdown (
text/markdown)- GitHub Flavored Markdown (GFM) by default
- Alternative: CommonMark
- Modern, widely supported format
- Excellent compatibility across platforms
Format Selection Strategy
Choose Markdown when:
- Starting a new project without existing RST documentation
- Prioritizing GitHub/GitLab compatibility
- Team prefers Markdown syntax
- Documentation is primarily user-facing
Choose reStructuredText when:
- Project uses Sphinx for documentation
- Need advanced table formatting
- Existing RST documentation infrastructure
- Using
sphinx-readmeto generate from Sphinx docs
Use sphinx-readme when:
- Maintaining Sphinx documentation alongside PyPI README
- Need consistent formatting between docs and README
- Want to leverage Sphinx features while generating PyPI-compatible output
- Converting Sphinx-heavy documentation to PyPI-friendly format
README Content Guidelines
Essential Sections
Include these sections for comprehensive project documentation:
Project Identity (Required)
- Project name and one-line description
- Badges (build status, PyPI version, license, coverage)
- Quick value proposition
Installation (Required)
- Primary installation method:
pip install package-name - Alternative methods:
uv add package-name, development installation - System requirements and Python version compatibility
Quick Start (Highly Recommended)
- Minimal working example (3-10 lines)
- Expected output or result
- Link to full documentation
Features (Recommended)
- Bulleted list of key capabilities
- What makes this package unique
- Comparison with alternatives (if applicable)
Usage Examples (Recommended)
- 2-3 concrete examples showing common use cases
- Progressive complexity (basic → intermediate)
- Code samples with expected output
Documentation Link (Required if comprehensive docs exist)
- Link to Read the Docs, GitHub Pages, or hosted documentation
- Brief description of what's in the full docs
Contributing (Recommended for open source)
- How to report issues
- How to submit changes
- Link to CONTRIBUTING.md if detailed
License (Required)
- License name and link to LICENSE file
- Brief permissions statement
Changelog/Release Notes (Optional)
- Link to CHANGELOG.md or GitHub releases
- Brief summary of latest version
Writing Style Principles
Follow these principles from documentation-expert and gitlab-docs-expert:
Clarity and Simplicity
- Write for users who are discovering your project for the first time
- Avoid jargon unless necessary and explained
- Use active voice and present tense
- Keep sentences concise (under 25 words)
Focus on the User
- Answer: "What can this do for me?" early
- Show working examples before explaining internals
- Provide copy-paste ready code snippets
- Include expected outputs to verify success
Accuracy and Synchronization
- Ensure code examples actually work with current version
- Test all commands before including
- Keep version numbers current
- Update README with each release
Promote Consistency
- Use consistent terminology throughout
- Follow same code style as project
- Match heading hierarchy (# → ## → ###)
- Use parallel structure in lists
Leverage Visuals and Examples
- Include code examples with syntax highlighting
- Show expected output or results
- Use badges for quick status information
- Consider diagrams for architecture (Mermaid on GitHub/GitLab)
Format-Specific Guidance
Markdown (README.md)
Syntax Highlighting
```python
import package_name
result = package_name.process("example")
print(result)
# Output: Processed: example
```
Badges



Tables
| Feature | Support |
|---------|---------|
| Python 3.11+ | ✓ |
| Type hints | ✓ |
| Async support | ✓ |
Alerts (GitHub/GitLab)
> [!NOTE]
> This feature requires Python 3.11 or higher.
> [!WARNING]
> Breaking changes in version 2.0. See migration guide.
Links
[Documentation](https://package-name.readthedocs.io)
[PyPI](https://pypi.org/project/package-name/)
[Issues](https://github.com/user/package-name/issues)
reStructuredText (README.rst)
Syntax Highlighting
.. code-block:: python
import package_name
result = package_name.process("example")
print(result)
# Output: Processed: example
Badges
.. image:: https://img.shields.io/pypi/v/package-name.svg
:target: https://pypi.org/project/package-name/
:alt: PyPI version
.. image:: https://img.shields.io/pypi/pyversions/package-name.svg
:alt: Python versions
Tables
+------------------+----------+
| Feature | Support |
+==================+==========+
| Python 3.11+ | ✓ |
+------------------+----------+
| Type hints | ✓ |
+------------------+----------+
Or using simple table syntax:
======== =========
Feature Support
======== =========
Python 3.11+ ✓
Type hints ✓
======== =========
Admonitions
.. note::
This feature requires Python 3.11 or higher.
.. warning::
Breaking changes in version 2.0. See migration guide.
.. tip::
Use the async API for better performance.
Links
`Documentation <https://package-name.readthedocs.io>`_
`PyPI <https://pypi.org/project/package-name/>`_
`Issues <https://github.com/user/package-name/issues>`_
Section Headers
================
Main Title
================
Section
=========
Subsection
-----------
Subsubsection
^^^^^^^^^^^^^^
Sphinx README Integration
For projects using Sphinx, leverage sphinx-readme to generate PyPI-compatible README.rst files.
Installation
uv add --group docs sphinx-readme
Configuration in conf.py
extensions = [
'sphinx_readme',
]
# Optional configuration
readme_config = {
'src_file': 'index.rst', # Source file in docs/
'out_file': '../README.rst', # Output to project root
}
Key Benefits
- Converts Sphinx-specific roles to PyPI-compatible equivalents
- Preserves admonitions, code blocks, and formatting
- Maintains single source of truth in Sphinx docs
- Automatically handles cross-references
Limitations
- Sphinx roles (
:py:func:,:ref:) converted to plain text or removed - Advanced Sphinx features may not translate
- Review generated output before publishing
Workflow
# Build Sphinx docs (generates README.rst automatically)
uv run sphinx-build -b html docs/ docs/_build/html
# Verify README rendering
uv run --with twine twine check dist/*
PyPI Integration
pyproject.toml Configuration
For Markdown README
[project]
name = "package-name"
version = "1.0.0"
description = "Short one-line description"
readme = "README.md" # Automatically sets content-type to text/markdown
requires-python = ">=3.11"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["keyword1", "keyword2"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
[project.urls]
Homepage = "https://github.com/user/package-name"
Documentation = "https://package-name.readthedocs.io"
Repository = "https://github.com/user/package-name"
Issues = "https://github.com/user/package-name/issues"
Changelog = "https://github.com/user/package-name/blob/main/CHANGELOG.md"
For reStructuredText README
[project]
readme = "README.rst" # Automatically sets content-type to text/x-rst
# ... rest of configuration
For custom content type
[project]
readme = {file = "README.md", content-type = "text/markdown"}
# or
readme = {file = "README.rst", content-type = "text/x-rst"}
For GitHub Flavored Markdown (explicit)
[project]
readme = {file = "README.md", content-type = "text/markdown; variant=GFM"}
For CommonMark
[project]
readme = {file = "README.md", content-type = "text/markdown; variant=CommonMark"}
Building and Publishing
Build distribution packages
# Using uv (modern approach)
uv build
# Outputs to dist/:
# - package_name-1.0.0-py3-none-any.whl
# - package_name-1.0.0.tar.gz
Validate README rendering
# Check that README will render on PyPI
uv run --with twine twine check dist/*
Expected output for success:
Checking dist/package_name-1.0.0-py3-none-any.whl: Passed
Checking dist/package_name-1.0.0.tar.gz: Passed
Common validation errors
| Error | Cause | Solution |
|---|---|---|
Unknown interpreted text role "py:func" |
Sphinx role in RST | Remove Sphinx-specific roles, use plain text |
Unexpected indentation |
RST indentation error | Fix indentation, ensure blank lines before/after directives |
Unknown directive type "automodule" |
Sphinx directive in RST | Remove Sphinx directives, use standard docutils only |
Invalid markup |
Malformed RST | Run rst2html.py README.rst /dev/null to test |
| Content not showing | Wrong content-type | Verify readme setting in pyproject.toml matches file format |
Publish to PyPI
# Upload to PyPI (requires API token)
uv run --with twine twine upload dist/*
# Test on TestPyPI first (recommended)
uv run --with twine twine upload --repository testpypi dist/*
Setting up PyPI credentials
# Create ~/.pypirc
cat > ~/.pypirc << 'EOF'
[pypi]
username = __token__
password = pypi-your-api-token-here
[testpypi]
username = __token__
password = pypi-your-testpypi-token-here
EOF
chmod 600 ~/.pypirc
Validation Workflow
Pre-Publish Checklist
Run this workflow before publishing to PyPI:
# 1. Build the package
uv build
# 2. Validate README rendering
uv run --with twine twine check dist/*
# 3. Test installation locally
uv pip install dist/*.whl
# 4. Upload to TestPyPI
uv run --with twine twine upload --repository testpypi dist/*
# 5. Visit TestPyPI page and verify README renders correctly
# https://test.pypi.org/project/package-name/
# 6. Test installation from TestPyPI
uv pip install --index-url https://test.pypi.org/simple/ package-name
# 7. If all looks good, upload to production PyPI
uv run --with twine twine upload dist/*
Local README Testing
Test Markdown rendering locally
# Install grip (GitHub README previewer)
uv tool install grip
# Preview README.md
uvx grip README.md
# Opens browser at http://localhost:6419
Test reStructuredText rendering locally
# Convert RST to HTML for preview
uv run --with docutils rst2html.py README.rst README.html
# Open in browser
xdg-open README.html # Linux
open README.html # macOS
Validate RST syntax
# Check for RST errors
uv run --with docutils rst2html.py README.rst /dev/null
# Only shows errors/warnings, no output file
Common Issues and Solutions
reStructuredText Issues
Issue: Sphinx roles not rendering
❌ WRONG (will fail on PyPI):
See :py:func:`package.function` for details.
Use :ref:`my-label` for more information.
✓ CORRECT (PyPI-compatible):
See ``package.function()`` for details.
Use `my-label`_ for more information.
.. _my-label: https://docs.example.com/section
Issue: Code block indentation
❌ WRONG:
.. code-block:: python
import package # No blank line, incorrect indent
✓ CORRECT:
.. code-block:: python
import package # Blank line after directive, proper indent
package.run()
Issue: Link definition spacing
❌ WRONG:
`Documentation`_
.. _Documentation: https://example.com # Too close
✓ CORRECT:
`Documentation`_
.. _Documentation: https://example.com # Blank line before
Markdown Issues
Issue: Code fence language specification
❌ WRONG:
```
import package # No language specified
```
✓ CORRECT:
```python
import package
```
Issue: Heading hierarchy
❌ WRONG:
# Title
### Subsection # Skipped ##
✓ CORRECT:
# Title
## Section
### Subsection
Cross-Platform Compatibility
Issue: Platform-specific line endings
# Convert to Unix line endings (LF)
dos2unix README.md # or README.rst
# Or using Python
uv run python -c "
import sys
with open('README.md', 'r') as f:
content = f.read()
with open('README.md', 'w', newline='\n') as f:
f.write(content)
"
Issue: Rendering differences GitHub vs PyPI
- GitHub: Supports GFM extensions (alerts, task lists, tables)
- PyPI: Supports basic GFM, but may render differently
- Solution: Test on TestPyPI before publishing
Example README Templates
See reference files for complete examples:
- ./references/markdown-template.md - Modern Markdown README template
- ./references/rst-template.rst - reStructuredText README template
- ./references/sphinx-readme-example.md - Using sphinx-readme extension
Related Skills and Tools
Skills to activate:
uv- For Python project and package managementhatchling- For build backend configurationgitlab-skill- For GitLab Flavored Markdown features
External tools:
twine- README validation and PyPI publishingsphinx-readme- Generate PyPI-compatible RST from Sphinxgrip- Preview Markdown as GitHub renders itdocutils- Validate and convert reStructuredTextpandoc- Convert between Markdown and RST
Quality Standards
Before finalizing a README:
- One-line description clearly states project purpose
- Installation instructions tested and accurate
- Code examples run successfully with current version
- All links valid and point to correct destinations
- Badges display correctly and are current
- Markup validated with
twine check - Tested rendering on target platforms (PyPI, GitHub/GitLab)
- Spelling and grammar checked
- Heading hierarchy is consistent (no skipped levels)
- License clearly stated
- Python version requirements specified
- Content type correctly set in pyproject.toml
Key Principles
- User-First Design: Answer "What does this do for me?" in the first paragraph
- Show, Don't Tell: Working code examples over abstract descriptions
- Platform Compatibility: Test rendering on all target platforms
- Format Constraints: Respect PyPI limitations (no Sphinx extensions in RST)
- Validation Before Publishing: Always run
twine checkbefore uploading - Single Source of Truth: Use
sphinx-readmefor Sphinx-based projects - Accessibility: Write for diverse audiences (beginners to experts)
- Maintenance: Update README with each release
References
Official Documentation
- Making a PyPI-friendly README - Official Python Packaging Guide
- PyPI README Renderer - PyPI's rendering engine
- sphinx-readme Documentation - Sphinx to PyPI README converter
- reStructuredText Primer - Sphinx RST guide
- GitHub Flavored Markdown - GFM specification
- CommonMark - CommonMark specification
Tool Documentation
- Twine Documentation - Package upload tool
- uv Documentation - Modern Python package manager
- Hatchling Documentation - Modern build backend
Related Resources
- readme-renderer on PyPI - Test README rendering
- Grip - Preview Markdown as GitHub renders
- m2rr - Markdown to reStructuredText converter
- Pandoc - Universal document converter