Create python project github en
Skill roebi/agent-skills/skills/create-python-project-github-en
agent skill library for ai agents using skills
npx -y skills add roebi/agent-skills --skill create-python-project-github-enAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Scaffold a complete, modern Python project from scratch - from mkdir to first PyPI publish. Use this skill whenever the user wants to create a new Python package, library, CLI tool, or PyPI module, start a new Python open-source project, set up GitHub Actions CI/CD for Python, or asks how to structure a modern Python project with packaging, testing, and devcontainer. Also triggers for "new pypi module", "python project template", "python package from scratch", "hatch", "uv init", or any request to bootstrap a Python repo with best practices.
The file declares its own license as CC BY-NC-SA 4.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
13.6 KB, as published. Nobody here has run it
Create Python Project (GitHub + PyPI)
Scaffold a complete modern Python project from mkdir to first PyPI publish.
Global Rules (apply to every phase)
ASCII Safety Rule - applies to all generated text, docs, code, and comments:
- Never use em-dash or long dash - use hyphen-minus (-) only.
- Never use Unicode arrows - use -> or <- only.
- UTF-8 coding declaration (
# -*- coding: utf-8 -*-) is NOT required in Python 3 (UTF-8 is the default). Omit it unless targeting legacy tooling.
Toolchain decisions (rationale in references/toolchain-rationale.md):
| Concern | Tool |
|---|---|
| Env / dep management | uv (never pip or pipx) |
| Build backend | hatchling |
| Linter + formatter | ruff |
| Test runner | pytest |
| Type checker | mypy (opt-in, not CI-blocking) |
| CI/CD | GitHub Actions |
| PyPI release | Trusted Publishing (OIDC, no tokens) |
| Devcontainer | .devcontainer/maintainer/ |
| Supply chain audit | pip-audit==2.10.0 |
| CLI framework | typer (gives --install-completion for free) |
Phase 0 - Gather inputs
Before writing any file, ask the user for:
PROJECT_NAME- the PyPI distribution name (e.g.my-cool-lib). Derived Python package name =PROJECT_NAMEwith hyphens -> underscores.PROJECT_DESCRIPTION- one-sentence summary.GITHUB_USER- GitHub username or org (for URLs in pyproject.toml).PYTHON_MIN- minimum Python version to support (default:3.12).PACKAGING_STYLE-library,cli, orboth.CLI_COMMAND(only if cli/both) - the console script name (e.g.my-tool).AUTHOR_NAMEandAUTHOR_EMAIL.
If already provided in the conversation, extract from context and confirm before proceeding.
Phase Check:
- All 7 inputs confirmed in writing before proceeding to Phase 1.
Phase 1 - Init repo
mkdir PROJECT_NAME
cd PROJECT_NAME
git init
git checkout -b main
Create .gitignore - use the template in references/gitignore.md.
Phase Check:
-
git statusshows clean repo with.gitignorepresent.
Phase 2 - LICENSE
Create LICENSE with the MIT license text:
MIT License
Copyright (c) YEAR AUTHOR_NAME
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Phase Check:
-
LICENSEfile exists with correct author and year.
Phase 3 - Source layout
Create the src/ layout (PEP 517 best practice):
PROJECT_NAME/
+-- src/
| +-- PACKAGE_NAME/
| +-- __init__.py # contains __version__ = "0.1.0"
+-- tests/
| +-- __init__.py
| +-- test_PACKAGE_NAME.py
+-- docs/
+-- .devcontainer/
| +-- maintainer/
+-- .github/
| +-- workflows/
+-- .gitignore
+-- CHANGELOG.md
+-- LICENSE
+-- README.md
+-- pyproject.toml
For cli/both style, also create src/PACKAGE_NAME/cli.py.
Seed src/PACKAGE_NAME/__init__.py:
"""PROJECT_DESCRIPTION"""
__version__ = "0.1.0"
Seed tests/test_PACKAGE_NAME.py:
"""Basic smoke tests for PACKAGE_NAME."""
import PACKAGE_NAME
def test_version():
assert PACKAGE_NAME.__version__ == "0.1.0"
Phase Check:
- Directory tree matches layout above.
-
__init__.pycontains__version__.
Phase 4 - pyproject.toml
Use the correct template from references based on packaging style:
- library ->
references/pyproject-library.toml.md - cli/both ->
references/pyproject-cli.toml.md
Substitute all PROJECT_NAME, PACKAGE_NAME, GITHUB_USER, AUTHOR_NAME,
AUTHOR_EMAIL, PYTHON_MIN placeholders.
Mandatory pyproject.toml fields (validate with check_pyproject_meta.py):
licensewith valueMITauthorswith name and emailkeywords(non-empty list)- classifiers including at least one
Programming Language :: Python :: 3.x [project.urls]with Homepage, Repository, Issues, Changeloghatchlingin[build-system.requires]only - never in dependency-groups
For CLI/both style, add typer to dependencies:
dependencies = [
"typer>=0.12",
]
Type stubs: For every third-party dependency lacking inline types, add its stub
to dev optional-dependencies (e.g. types-PyYAML, types-requests).
Phase Check:
-
uv syncruns without errors. -
python check_pyproject_meta.pypasses all 18 tests.
Phase 5 - Supply Chain Rules
Python supply chain defaults - non-negotiable:
- Use
uv(never pip, never pipx) for all installs. uv lock+uv syncfor reproducible installs.- Pin dependencies with version bounds in
pyproject.toml. - Only use PyPI package versions older than 3 days (avoid same-day releases).
- Secrets go in Jenkins Credentials Store - never in
.envfiles. - Run services in isolated Podman - never with host-mounted
~/.ssh.
Dockerfile supply chain audit pattern (Python):
# Install tools via uv
RUN uv tool install ruff
# Audit step (pip-audit has no uv equivalent yet)
RUN pip install --no-cache-dir "pip-audit==2.10.0" \
&& pip-audit --skip-editable \
&& pip uninstall -y pip-audit
Phase Check:
-
pyproject.tomlhas pinned version bounds for all dependencies. - Dockerfile (if present) includes pip-audit audit step.
- No secrets in
.env- confirmed.
Phase 6 - CLI entry point
Skip this phase if PACKAGING_STYLE is library.
Use Typer - it provides --install-completion for bash/zsh/fish for free.
Seed src/PACKAGE_NAME/cli.py:
"""CLI entry point for PROJECT_NAME."""
from __future__ import annotations
import typer
app = typer.Typer(help="PROJECT_DESCRIPTION")
@app.command()
def main(
version: bool = typer.Option(False, "--version", help="Show version and exit."),
) -> None:
"""Main entry point."""
if version:
import PACKAGE_NAME
typer.echo(f"PROJECT_NAME {PACKAGE_NAME.__version__}")
raise typer.Exit()
# TODO: implement commands here
typer.echo("Hello from PROJECT_NAME!")
if __name__ == "__main__":
app()
After install, show the user how to enable shell completion:
# bash
CLI_COMMAND --install-completion bash
# zsh
CLI_COMMAND --install-completion zsh
# verify
CLI_COMMAND --help
Phase Check:
-
uv run CLI_COMMAND --helpruns without errors. -
uv run CLI_COMMAND --install-completion bashruns without errors. -
uv run CLI_COMMAND --versionprints the correct version.
Phase 7 - Devcontainer
Create .devcontainer/maintainer/devcontainer.json using the template in
references/devcontainer.md.
Phase Check:
-
.devcontainer/maintainer/devcontainer.jsonis valid JSON.
Phase 8 - GitHub Actions
CI workflow
Create .github/workflows/ci.yml using the template in
references/ci-workflow.md.
Python version matrix - always include all three:
python-version: ["3.12", "3.13", "3.14"] # adjust lower bound to PYTHON_MIN
Add a mandatory pip-audit job to ci.yml:
audit:
name: Supply chain audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Install dependencies
run: uv sync --extra dev
- name: pip-audit
run: uv run pip-audit --skip-editable
CI job order: lint -> typecheck -> audit -> test (fail fast on lint/audit before burning test matrix minutes).
Publish workflow
Create .github/workflows/publish.yml using the template in
references/publish-workflow.md.
Trusted Publishing (OIDC) requirements:
environment: name: pypipermissions: id-token: writeattestations: true- No
PYPI_TOKENsecret needed.
Issue triage workflow
Create .github/workflows/set-label-triage-to-new-issue.yml:
name: Triage new issues
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['triage']
})
Phase Check:
- CI workflow YAML is valid.
- Matrix includes
3.14as highest version. -
auditjob present and runs beforetest. - Publish workflow triggers only on
v*tags. -
environment: pypipresent in publish workflow.
Phase 9 - CHANGELOG and README
CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.0] - YYYY-MM-DD
### Added
- Initial release
README.md
Required sections: title, description, CI/PyPI/Python/License badges, Install,
Usage, Development (uv sync --all-extras, uv run ruff check ., uv run pytest),
Shell completion section (CLI projects only: CLI_COMMAND --install-completion bash),
License line pointing to LICENSE (MIT).
Phase Check:
-
CHANGELOG.mdhas[Unreleased]section. -
README.mdhas install instructions and CI badge.
Phase 10 - First commit and PyPI Trusted Publishing setup
uv sync
uv run ruff check .
uv run ruff format --check .
uv run pytest
uv build
git add .
git commit -m "chore: initial project scaffold"
git remote add origin https://github.com/GITHUB_USER/PROJECT_NAME.git
git push -u origin main
Then instruct the user to configure Trusted Publishing on pypi.org:
- Go to https://pypi.org/manage/account/publishing/
- Add a new Trusted Publisher:
- PyPI project name:
PROJECT_NAME - GitHub owner:
GITHUB_USER - Repository name:
PROJECT_NAME - Workflow filename:
publish.yml - Environment name:
pypi
- PyPI project name:
- Push a tag to trigger the first publish:
git tag v0.1.0
git push origin v0.1.0
Phase Check:
-
uv run ruff check .returns no violations. -
uv run ruff format --check .returns no violations. -
uv run pytestpasses. -
uv buildproduces.whland.tar.gzindist/. - Push to
mainsucceeds. - Trusted Publishing configured on pypi.org.
Phase 11 - Delivery Standard
When delivering a project or multi-file output, always package it as a .tar.gz
archive. The archive is the canonical deliverable.
tar --exclude='.venv' \
--exclude='.git' \
--exclude='__pycache__' \
--exclude='.pytest_cache' \
--exclude='dist' \
-czf PROJECT_NAME.tar.gz PROJECT_NAME/
Present the archive as the primary download. Individual files may also be shown but the archive is the canonical deliverable.
Phase Check:
- Archive excludes
.venv,.git,__pycache__,.pytest_cache,dist/. - Archive extracts cleanly and
uv syncworks from the extracted directory.
Reference files
Read these when needed - do not load all at once:
| File | When to read |
|---|---|
references/pyproject-library.toml.md | Phase 4, library style |
references/pyproject-cli.toml.md | Phase 4, cli/both style |
references/ci-workflow.md | Phase 8, CI workflow |
references/publish-workflow.md | Phase 8, publish workflow |
references/devcontainer.md | Phase 7, devcontainer |
references/gitignore.md | Phase 1, .gitignore |
references/toolchain-rationale.md | If user asks why a tool was chosen |