Agent skill
pypi-server
Guidance for creating Python packages and serving them via a local PyPI server. This skill applies when tasks involve building Python packages (with pyproject.toml or setup.py), setting up local package repositories, or serving packages via HTTP for pip installation. Use when the goal is to create installable Python packages and make them available through a local index URL.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/pypi-server
SKILL.md
PyPI Server Skill
This skill provides guidance for creating Python packages and serving them through a local PyPI server for installation via pip.
When to Use This Skill
This skill applies to tasks that involve:
- Creating Python packages with custom modules
- Building distributable packages (.tar.gz, .whl files)
- Setting up a local PyPI-compatible server
- Making packages installable via
pip install --index-url
Environment Assessment (Critical First Step)
Before starting any work, assess the execution environment to avoid compatibility issues:
# Check Python version - critical for tool compatibility
python3 --version
# Check available package tools
which pip3 && pip3 --version
which uv 2>/dev/null # Fast package manager alternative
# Check for process management tools
which pkill lsof fuser 2>/dev/null || echo "Limited process tools"
Key compatibility consideration: Python 3.13+ removed the cgi module, which breaks pypiserver. Plan for fallback approaches if using Python 3.13+.
Approach Selection
Option 1: Built-in HTTP Server (Recommended for Python 3.13+)
Use Python's built-in http.server module - no external dependencies, works across all Python versions.
Directory structure required:
server-root/
└── simple/
└── packagename/
├── packagename-0.1.0.tar.gz
└── packagename-0.1.0-py3-none-any.whl
Server command:
cd server-root && python3 -m http.server 8080
Option 2: pypiserver (Python < 3.13 only)
More feature-rich but has Python version constraints.
pip install pypiserver
pypi-server run -p 8080 ./packages/
Note: The command is pypi-server (with hyphen), not pypiserver.
Package Creation Workflow
Step 1: Create Package Structure
packagename/
├── pyproject.toml
├── src/
│ └── packagename/
│ └── __init__.py
Or flat layout:
packagename/
├── pyproject.toml
└── packagename/
└── __init__.py
Step 2: Configure pyproject.toml
Minimal configuration:
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "packagename"
version = "0.1.0"
description = "Package description"
requires-python = ">=3.8"
Step 3: Build the Package
cd packagename
pip install build
python -m build
This creates dist/packagename-0.1.0.tar.gz and dist/packagename-0.1.0-py3-none-any.whl.
Server Setup Workflow
Step 1: Create Server Directory Structure
mkdir -p pypi-server/simple/packagename
cp packagename/dist/* pypi-server/simple/packagename/
Step 2: Start the Server
Important: Track the working directory from which the server starts. The server will only serve files relative to its starting directory.
cd pypi-server && python3 -m http.server 8080 &
Record the PID for later cleanup:
echo $! > server.pid
Step 3: Verify Server Accessibility
# Check root endpoint
curl -s http://localhost:8080/
# Check simple index (this is what pip uses)
curl -s http://localhost:8080/simple/
# Check package listing
curl -s http://localhost:8080/simple/packagename/
Verification Strategy
Test Package Installation
pip install --index-url http://localhost:8080/simple packagename==0.1.0
Test Package Functionality
import packagename
# Test the actual functionality
Full Verification Checklist
- Server responds on root endpoint (
/) - Server responds on
/simple/endpoint - Package files are listed at
/simple/packagename/ pip installsucceeds with explicit index URL- Installed package imports correctly
- Package functionality works as expected
Process Management
Starting Background Servers
# Start with explicit working directory tracking
cd /path/to/server-root
python3 -m http.server 8080 &
SERVER_PID=$!
echo "Server PID: $SERVER_PID"
Checking Server Status
# Check if port is in use
python3 -c "import socket; s=socket.socket(); s.settimeout(1); result=s.connect_ex(('localhost', 8080)); print('Port in use' if result==0 else 'Port free'); s.close()"
# List processes on port (if tools available)
lsof -i :8080 2>/dev/null || fuser 8080/tcp 2>/dev/null
Stopping Servers
# If PID is known
kill $SERVER_PID
# If PID unknown, find and kill
pkill -f "http.server 8080" 2>/dev/null
# Fallback: use /proc filesystem
for pid in /proc/[0-9]*; do
if grep -q "http.server" "$pid/cmdline" 2>/dev/null; then
kill "$(basename $pid)" 2>/dev/null
fi
done
Common Pitfalls and Solutions
Pitfall 1: Server Running from Wrong Directory
Symptom: Server running but /simple/ returns 404.
Cause: A previous server instance started from a different directory is still running.
Solution: Kill all HTTP server processes, verify port is free, then restart from the correct directory.
Pitfall 2: Port Already in Use
Symptom: "Address already in use" error when starting server.
Solution: Find and kill the process using the port, or use a different port.
Pitfall 3: pypiserver Fails on Python 3.13+
Symptom: Import error about missing cgi module.
Solution: Use the built-in http.server approach instead.
Pitfall 4: pip Can't Find Package
Symptom: pip install fails with "No matching distribution found."
Possible causes:
- Incorrect directory structure (must be
/simple/packagename/) - Server not running or wrong port
- Package files not copied to server directory
- Version mismatch in install command
Debug approach:
# Verify server response includes package files
curl http://localhost:8080/simple/packagename/
Pitfall 5: Package Installs but Import Fails
Symptom: pip install succeeds but import packagename fails.
Cause: Package structure issue - the importable name may differ from the package name.
Solution: Verify __init__.py exists and the package structure matches pyproject.toml configuration.
Clean State Management
Before starting server operations, ensure a clean state:
- Kill any existing servers on the target port
- Verify port is free
- Remove stale server directories if recreating
- Start fresh server with explicit directory
This prevents confusion from orphaned processes or stale state.
Didn't find tool you were looking for?