Skip to content

Commit ddcf260

Browse files
Naaremanclaude
andcommitted
Initial release: pyckage Claude Code skill
R-inspired philosophy for building Python packages the right way. Covers scaffolding, API design, testing, docs, lifecycle, and release using uv, rich, pytest, and mkdocs-material. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 parents  commit ddcf260

File tree

10 files changed

+1329
-0
lines changed

10 files changed

+1329
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
extracted/
3+
*.zip

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Nareman
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# pyckage
2+
3+
> *"Just as Hadley Wickham brought the Grammar of Graphics to R as ggplot2, pyckage brings the philosophy of R package development to Python."*
4+
5+
## What is pyckage?
6+
7+
**pyckage** is a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) skill that teaches Claude how to build Python packages the right way — using the hard-won wisdom of the R package ecosystem.
8+
9+
Python has incredible packages. But it has never had a unified philosophy for *building* them. The R world has one: Hadley Wickham's [*R Packages*](https://r-pkgs.org/) book (with Jenny Bryan), backed by tools like `devtools`, `usethis`, `roxygen2`, `cli`, and `lifecycle`.
10+
11+
pyckage translates that philosophy into Python using modern tools: `uv`, `rich`, `pytest`, and `mkdocs-material`.
12+
13+
## Installation
14+
15+
### For all your projects (personal scope)
16+
17+
```bash
18+
# Clone the repo
19+
git clone https://github.com/Naareman/pyckage.git
20+
21+
# Copy to your Claude skills directory
22+
cp -r pyckage ~/.claude/skills/pyckage
23+
```
24+
25+
### For a single project (project scope)
26+
27+
```bash
28+
# From your project root
29+
mkdir -p .claude/skills
30+
cp -r /path/to/pyckage .claude/skills/pyckage
31+
```
32+
33+
### Verify it's installed
34+
35+
In Claude Code, run `/pyckage` — you should see it in the skill list.
36+
37+
## Usage
38+
39+
pyckage activates automatically when you're working on Python package tasks. You can also invoke it explicitly:
40+
41+
```
42+
/pyckage scaffold my-new-package # Create a new package from scratch
43+
/pyckage api # Review and improve your API design
44+
/pyckage test # Set up or improve tests
45+
/pyckage docs # Set up mkdocs + docstrings
46+
/pyckage lifecycle # Manage deprecations and versioning
47+
/pyckage release # Walk through the PyPI release ritual
48+
/pyckage # Assess your project against all 5 principles
49+
```
50+
51+
Or just describe what you need — pyckage will activate when it recognizes a Python packaging task:
52+
53+
- *"I want to make a Python library"*
54+
- *"Help me structure my code as a package"*
55+
- *"How should I name these functions?"*
56+
- *"How do I publish to PyPI?"*
57+
58+
## The Philosophy (what R taught us)
59+
60+
### 1. User communication is a first-class concern
61+
R's `cli` package made it easy to produce beautiful, structured messages. **pyckage** brings this to Python through `rich` and structured exception hierarchies.
62+
63+
### 2. Function names form a grammar
64+
Tidyverse packages use `verb_noun()` consistently. Users can *guess* function names because the grammar is predictable. **pyckage** encodes naming conventions that make your API feel intentional.
65+
66+
### 3. Lifecycle deserves ceremony
67+
R's `lifecycle` package gave deprecations a formal process. Users are never surprised. **pyckage** brings the same discipline to Python's `warnings` system.
68+
69+
### 4. Documentation lives next to code
70+
`roxygen2` made it impossible to forget documentation. **pyckage** enforces Google-style docstrings + `mkdocstrings` so docs are always a byproduct of writing good code.
71+
72+
### 5. There is a whole game
73+
Before diving into details, you should be able to see the whole thing working end-to-end. **pyckage** gives you a complete, working package skeleton from the first command.
74+
75+
## What pyckage Covers
76+
77+
| Stage | R equivalent | Python (pyckage) |
78+
|---|---|---|
79+
| Scaffold | `usethis::create_package()` | `uv init` + src layout |
80+
| Dependency management | `DESCRIPTION` + `devtools` | `pyproject.toml` + `uv` |
81+
| User messages | `cli` package | `rich` Console |
82+
| Structured errors | `rlang::abort()` | Custom exception hierarchy |
83+
| API naming | tidyverse conventions | `verb_noun`, families, prefixes |
84+
| Testing | `testthat` | `pytest` + fixtures |
85+
| Documentation | `roxygen2` + `pkgdown` | Google docstrings + `mkdocs-material` |
86+
| Lifecycle | `lifecycle` package | `warnings` + deprecation conventions |
87+
| Release | `devtools::release()` | GitHub Actions + PyPI |
88+
89+
## Skill Structure
90+
91+
```
92+
pyckage/
93+
├── SKILL.md # Main skill definition (philosophy + routing)
94+
├── README.md # This file
95+
├── LICENSE # MIT
96+
└── references/
97+
├── 01-scaffold.md # Package scaffolding (the "whole game")
98+
├── 02-api-design.md # Naming, messages, errors
99+
├── 03-testing.md # pytest conventions and patterns
100+
├── 04-docs.md # Docstrings + mkdocs-material
101+
├── 05-lifecycle.md # Deprecation ceremony + versioning
102+
└── 06-release.md # PyPI publishing + GitHub Actions
103+
```
104+
105+
## Contributing
106+
107+
This project is opinionated by design. If you think a convention is wrong, open an issue — but bring a reason, not just a preference. The goal is a *philosophy*, not a menu of options.
108+
109+
## License
110+
111+
MIT

SKILL.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
name: pyckage
3+
description: >
4+
Build Python packages the right way — R-inspired philosophy for scaffolding, API design,
5+
testing, docs, deprecation lifecycle, and PyPI release using uv, rich, pytest, and
6+
mkdocs-material. Activate when creating/structuring Python packages, designing APIs,
7+
naming functions, adding user messages/errors, writing tests, setting up docs, managing
8+
deprecations, or publishing to PyPI.
9+
argument-hint: "[scaffold|api|test|docs|lifecycle|release] [package-name]"
10+
---
11+
12+
# pyckage
13+
14+
A skill for building Python packages with the philosophy of the R package ecosystem:
15+
clear user communication, principled API design, living documentation, and ceremonial lifecycle management.
16+
17+
The guiding question for every decision: *"What would make this package feel like a thoughtful, professional tool — not just a collection of functions?"*
18+
19+
---
20+
21+
## How This Skill Is Organized
22+
23+
This SKILL.md gives you the philosophy and the map. For implementation details, read the
24+
relevant reference file from `references/`:
25+
26+
| What you're doing | Read |
27+
|---|---|
28+
| Starting a new package or setting up structure | [references/01-scaffold.md](references/01-scaffold.md) |
29+
| Designing function names, errors, user messages | [references/02-api-design.md](references/02-api-design.md) |
30+
| Writing or organizing tests | [references/03-testing.md](references/03-testing.md) |
31+
| Setting up or writing documentation | [references/04-docs.md](references/04-docs.md) |
32+
| Adding deprecations or managing versions | [references/05-lifecycle.md](references/05-lifecycle.md) |
33+
| Releasing to PyPI or setting up CI/CD | [references/06-release.md](references/06-release.md) |
34+
35+
Read only what's relevant to the current task. Don't load everything at once.
36+
37+
---
38+
39+
## The Five Principles
40+
41+
Before touching any reference file, internalize these. They inform every decision.
42+
43+
### 1. User communication is a first-class concern
44+
Every message a user sees — errors, warnings, progress, success — should be intentional.
45+
Use `rich` for structure and color. Use a consistent message hierarchy. Never let a raw
46+
traceback be the user's only feedback. The R `cli` package set this standard; `rich` is how
47+
we meet it in Python.
48+
49+
### 2. Function names form a grammar
50+
Names should be guessable. Use `verb_noun()` patterns. Group related functions with shared
51+
prefixes. A user should be able to predict `read_parquet()` after seeing `read_csv()`.
52+
Consistency is more important than cleverness.
53+
54+
### 3. Lifecycle deserves ceremony
55+
Deprecations are promises to users. When something changes, warn early, warn clearly, and
56+
give users a path forward. Never silently break things. Never deprecate without a timeline.
57+
58+
### 4. Documentation lives next to code
59+
Docstrings are not optional and not a final step. They are written at the same time as the
60+
function. Use Google style consistently. `mkdocstrings` turns them into a website automatically.
61+
62+
### 5. There is a whole game
63+
A user should be able to see a complete, working package early — not after mastering every
64+
detail. Scaffold first, refine later.
65+
66+
---
67+
68+
## Anatomy of a pyckage-style Package
69+
70+
```
71+
my-package/
72+
├── pyproject.toml ← single source of truth (uv-managed)
73+
├── README.md ← the story and quickstart
74+
├── CHANGELOG.md ← user-facing version history
75+
├── mkdocs.yml ← docs config (project root, not inside docs/)
76+
├── src/
77+
│ └── my_package/
78+
│ ├── __init__.py ← clean public API surface
79+
│ ├── py.typed ← PEP 561 marker for type checkers
80+
│ ├── errors.py ← structured exception hierarchy (public contract)
81+
│ ├── _messages.py ← rich console, message helpers
82+
│ └── core.py ← actual logic
83+
├── tests/
84+
│ ├── conftest.py ← shared fixtures
85+
│ └── test_core.py
86+
└── docs/
87+
├── index.md
88+
└── api.md
89+
```
90+
91+
Key decisions encoded here:
92+
- **src layout** always — prevents accidental imports from the project root
93+
- **`errors.py`** is always its own file — errors are a public contract (no underscore: users import these directly)
94+
- **`_messages.py`** centralizes all user-facing output — never scattered `print()` calls
95+
- **`__init__.py`** is curated, not auto-imported — users see only what's intentional
96+
97+
---
98+
99+
## Argument Routing
100+
101+
When invoked with `/pyckage <subcommand>`, route based on the first argument:
102+
103+
| Invocation | Action |
104+
|---|---|
105+
| `/pyckage scaffold <name>` | Read [references/01-scaffold.md](references/01-scaffold.md) and create a new package named `<name>` |
106+
| `/pyckage api` | Read [references/02-api-design.md](references/02-api-design.md) and review/improve the current package's API |
107+
| `/pyckage test` | Read [references/03-testing.md](references/03-testing.md) and set up or improve tests |
108+
| `/pyckage docs` | Read [references/04-docs.md](references/04-docs.md) and set up or improve documentation |
109+
| `/pyckage lifecycle` | Read [references/05-lifecycle.md](references/05-lifecycle.md) and manage deprecations |
110+
| `/pyckage release` | Read [references/06-release.md](references/06-release.md) and walk through the release ritual |
111+
| `/pyckage` (no args) | Assess the current project against all five principles and suggest improvements |
112+
113+
When invoked without a subcommand (auto-triggered or plain `/pyckage`), use the Quick Decision Guide below.
114+
115+
---
116+
117+
## Quick Decision Guide
118+
119+
**User asks to scaffold / create a new package:**
120+
→ Read [references/01-scaffold.md](references/01-scaffold.md). Walk through the whole game first.
121+
122+
**User asks about function names, API shape, or error messages:**
123+
→ Read [references/02-api-design.md](references/02-api-design.md). Apply naming conventions and message hierarchy.
124+
125+
**User asks about tests or is writing test code:**
126+
→ Read [references/03-testing.md](references/03-testing.md). Enforce pytest conventions and fixture patterns.
127+
128+
**User asks about docs, docstrings, or mkdocs:**
129+
→ Read [references/04-docs.md](references/04-docs.md). Enforce Google docstrings and mkdocs-material setup.
130+
131+
**User mentions deprecating something, versioning, or breaking changes:**
132+
→ Read [references/05-lifecycle.md](references/05-lifecycle.md). Apply the deprecation ceremony.
133+
134+
**User wants to publish, release, or set up CI:**
135+
→ Read [references/06-release.md](references/06-release.md). Walk through PyPI + GitHub Actions setup.
136+
137+
**Multiple concerns at once:**
138+
→ Read the most relevant reference first. Reference others by name when needed.
139+
140+
---
141+
142+
## Tone When Helping
143+
144+
- Be opinionated. This skill exists to have opinions. Don't offer five options when one is right.
145+
- Explain the *why* behind conventions, especially when they come from the R world.
146+
- When translating an R concept to Python, name the translation explicitly:
147+
`"This is the Python equivalent of rlang::abort() — here's how it maps."`
148+
- Push back gently on anti-patterns (scattered `print()`, flat structure, inconsistent names)
149+
but always offer the better path immediately.

0 commit comments

Comments
 (0)