writing-python-scripts

Single-file Python scripts with PEP 722 inline metadata, uv run, and typer CLI. Use when creating standalone scripts or small automations.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "writing-python-scripts" with this command: npx skills add quick-brown-foxxx/coding_rules_python/quick-brown-foxxx-coding-rules-python-writing-python-scripts

Writing Python Scripts

Single-file scripts use PEP 722 inline metadata for dependencies, executed via uv run --script. All type safety and error handling rules from writing-python-code still apply.


When to Use Single Script

Single Script (PEP 722)Full Project
One task, one fileMultiple features
No tests neededTests required
Templating / generation / automationApplication with UI or API
Run directly: ./script.pyRun via: uv run poe app
Dependencies in script headerDependencies in pyproject.toml
Under ~500 linesWill grow beyond ~500 lines

Layout

app/
├── script.py             # Self-contained with inline deps
├── template.html         # Jinja2 templates (if generating text)
├── schema.json           # Validation schema (if validating configs)
├── configs/              # Configuration files (if multiple are needed)
├── pyproject.toml        # Tool config only (ruff, basedpyright)
└── .gitignore

Script Template

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.14"
# dependencies = [
#     "typer>=0.12.0",
#     "rusty-results>=1.1.1",
#     # Add as needed:
#     # "jinja2>=3.1.0",       # For text output generation
#     # "pyyaml>=6.0.0",       # For YAML config loading
#     # "jsonschema>=4.20.0",  # For config validation
# ]
# ///

import sys
from pathlib import Path
from typing import Final, TypedDict, Required

import typer
from rusty_results import Result, Ok, Err

# =============================================================================
# Constants & Types
# =============================================================================

TEMPLATE_PATH: Final[Path] = Path(__file__).parent / "template.html"

class ItemConfig(TypedDict):
    name: Required[str]
    # ...

# =============================================================================
# Business Logic
# =============================================================================

def load_config(path: Path) -> Result[ItemConfig, str]: ...
def process_item(config: ItemConfig) -> Result[str, str]: ...

# =============================================================================
# CLI Interface
# =============================================================================

app = typer.Typer(help="Description", add_completion=False)

@app.command()
def main_command() -> None:
    result = do_work()
    if result.is_err:
        typer.echo(f"Error: {result.unwrap_err()}", err=True)
        sys.exit(1)
    typer.echo(result.unwrap())

if __name__ == "__main__":
    app()

Tool Config (pyproject.toml)

No [project] section needed — just ruff + basedpyright config:

[tool.basedpyright]
pythonVersion = "3.14"
typeCheckingMode = "strict"
reportAny = "error"

[tool.ruff]
line-length = 120
target-version = "py314"

[tool.ruff.lint]
extend-select = ["E", "F", "I", "N", "UP", "S", "B", "A", "C4", "RUF"]
ignore = ["S101", "B008", "RUF001"]

CLI Note

Use typer for all scripts with uv. Use argparse only if the script must work without any external dependencies (stdlib-only, no uv).

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

writing-python-code

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

building-multi-ui-apps

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

testing-python

No summary provided by upstream source.

Repository SourceNeeds Review