Skip to content

Commit bbc8749

Browse files
committed
Simplify CLAUDE.md and preserve user-created skills
- Reduce CLAUDE.md from ~127 lines to ~30, keeping essential info - Move README and type annotation guidelines to dedicated skills - Update agent.py to only remove orphaned plain-* skills, preserving user-created skills that don't have the plain- prefix - Add docstring style guideline to plain-fix skill
1 parent 53985f6 commit bbc8749

File tree

5 files changed

+132
-116
lines changed

5 files changed

+132
-116
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
name: annotations
3+
description: Workflow for adding type annotations to Plain packages. Use this when adding or improving type coverage.
4+
---
5+
6+
# Type Annotation Workflow
7+
8+
We are gradually adding type annotations using Python 3.13+.
9+
10+
## Workflow
11+
12+
1. **Check current coverage**:
13+
14+
```
15+
uv run plain code annotations <directory> --details
16+
```
17+
18+
2. **Add annotations**: Focus on function/method signatures (parameters and return types)
19+
20+
3. **Type check**:
21+
22+
```
23+
./scripts/type-check <directory>
24+
```
25+
26+
4. **Format**: `./scripts/fix`
27+
28+
5. **Test**: `./scripts/test <package>`
29+
30+
6. **Verify improvement**:
31+
32+
```
33+
uv run plain code annotations <directory>
34+
```
35+
36+
7. **Add to validation**: Once a directory reaches 100% coverage, add it to `FULLY_TYPED_PATHS` in `scripts/type-validate`
37+
38+
## Guidelines
39+
40+
- Add `from __future__ import annotations` when necessary
41+
- Focus on public APIs and user-facing methods first
42+
- Don't annotate `__init__` return types (type checkers infer `None`)
43+
- Use explicit `return None` for functions with `-> Type | None` return type
44+
- Some Django-style ORM patterns are inherently difficult to type - that's okay
45+
- Goal is progress, not perfection
46+
47+
## Example
48+
49+
```bash
50+
# Check coverage
51+
uv run plain code annotations plain/plain/assets --details
52+
53+
# After adding annotations...
54+
./scripts/type-check plain/plain/assets
55+
./scripts/fix
56+
./scripts/test plain
57+
uv run plain code annotations plain/plain/assets # Should show 100%
58+
```

.claude/skills/readme/SKILL.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
name: readme
3+
description: Guidelines for writing and editing Plain package READMEs. Use this when creating or updating README files.
4+
---
5+
6+
# README Guidelines
7+
8+
Each top-level package directory (e.g., `plain-api/`) has a `README.md` symlink pointing to the actual README inside the package (e.g., `plain-api/plain/api/README.md`). **Only edit the README inside the package itself.**
9+
10+
See [`plain-jobs/plain/jobs/README.md`](plain-jobs/plain/jobs/README.md) as a good example.
11+
12+
## Purpose
13+
14+
The README answers: "How do I use this?" It gets users productive quickly and points them to code for deeper exploration. It is not a complete API reference.
15+
16+
## Required Structure
17+
18+
Every README follows this order:
19+
20+
1. **h1** with package name
21+
2. **Bold one-liner** describing the package
22+
3. **Table of contents** with links to h2s and h3s
23+
4. **Overview** section with basic working examples
24+
5. **Feature sections** as needed
25+
6. **FAQs** section (second to last) using h4s for questions
26+
7. **Installation** section (always last)
27+
28+
## Style
29+
30+
- **Conversational tone**: "You can..." not "The module provides..."
31+
- **First code example must be copy-paste ready** with imports included
32+
- **Subsequent examples can be minimal**, building on what was shown
33+
- **Link to source for advanced features**: `[ClassName](./file.py#ClassName)`
34+
- **Cross-package references**: `[plain.auth](../../plain-auth/plain/auth/README.md)`
35+
36+
## What to Document
37+
38+
- **If users import it, document it**
39+
- **Mention all public features**, even advanced ones briefly, then link to code
40+
- **Internal APIs stay undocumented** (`_prefix` functions and `@internalcode`)
41+
- **Don't fully document every parameter** - mention features exist, link to code
42+
43+
## Writing Tips
44+
45+
- Keep paragraphs short
46+
- Put takeaways up front
47+
- Use bullets and tables
48+
- Bold important text
49+
- Keep sentences simple and unambiguous

CLAUDE.md

Lines changed: 17 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,29 @@
11
# Claude
22

3-
## Commands and tools
3+
## After making code changes
44

5-
- Open a Python shell: `uv run python`
6-
- Run tests on all packages (or specify a package to test): `./scripts/test [package] [pytest options]`
7-
- Lint and format code: `./scripts/fix`
8-
- Make database migrations: `./scripts/makemigrations`
5+
1. **Format and lint**: `./scripts/fix` (always run this before committing)
6+
2. **Run tests**: `./scripts/test [package]`
97

10-
## Scratch directory
11-
12-
Use the `scratch` directory for one-off scripts, temporary files, and experimentation. This directory is gitignored. Write temporary files here instead of `/tmp`.
13-
14-
## Testing changes
15-
16-
The `example` directory contains a demo app with all Plain packages installed. You can `cd` into `example` and use `uv run plain`.
17-
18-
## READMEs
19-
20-
Each top-level package directory (e.g., `plain-api/`) has a `README.md` symlink pointing to the actual README inside the package (e.g., `plain-api/plain/api/README.md`). Only edit the README inside the package itself.
21-
22-
The README answers: "How do I use this?" It's not a complete API reference. It gets users productive quickly and points them to code for deeper exploration. See [`plain-jobs/plain/jobs/README.md`](plain-jobs/plain/jobs/README.md) as a good example.
23-
24-
### Structure
25-
26-
Every README should follow this order:
27-
28-
1. **h1** with package name
29-
2. **Bold one-liner** describing the package in one sentence
30-
3. **Table of contents** with links to h2s and h3s
31-
4. **Overview** section with basic working examples
32-
5. **Feature sections** as needed
33-
6. **FAQs** section (second to last) using h4s for questions
34-
7. **Installation** section (always last) - gets user from nothing to something working
35-
36-
### Style
37-
38-
- **Conversational tone**: "You can..." not "The module provides..."
39-
- **First code example must be copy-paste ready** with imports included
40-
- **Subsequent examples can be minimal**, building on what was shown
41-
- **Link to source for advanced features**: `[ClassName](./file.py#ClassName)`
42-
- **Cross-package references link to READMEs**: `[plain.auth](../../plain-auth/plain/auth/README.md)`
8+
## Commands
439

44-
### What to document
10+
| Command | Purpose |
11+
| ---------------------------- | -------------------------- |
12+
| `./scripts/fix` | Format and lint code |
13+
| `./scripts/test [package]` | Run tests |
14+
| `./scripts/makemigrations` | Create database migrations |
15+
| `./scripts/type-check <dir>` | Type check a directory |
16+
| `uv run python` | Open Python shell |
4517

46-
- **If users import it, document it** - that's the bar for what needs docs
47-
- **Mention all public features**, even advanced ones briefly, then link to code
48-
- **Internal APIs stay undocumented** - `_prefix` functions and `@internalcode` decorated items are invisible to docs
49-
- **Don't fully document every parameter** - mention the feature exists, link to code for details
50-
51-
## Type annotations
52-
53-
We are gradually adding type annotations to improve IDE/type checker friendliness. We are using Python 3.13+. Use the following workflow:
54-
55-
1. **Check current coverage**: `uv run plain code annotations <directory> --details`
56-
2. **Add annotations**: Focus on function/method signatures (parameters and return types)
57-
3. **Type check**: `./scripts/type-check <directory>` (uses `uv run ty check`)
58-
4. **Format**: `./scripts/fix`
59-
5. **Test**: `./scripts/test <package>`
60-
6. **Verify improvement**: `uv run plain code annotations <directory>`
61-
7. **Add to validation**: Once a directory reaches 100% coverage, add it to `FULLY_TYPED_PATHS` in `scripts/type-validate` to prevent regressions
62-
63-
Guidelines:
64-
65-
- Add `from __future__ import annotations` when necessary
66-
- Focus on public APIs and user-facing methods first
67-
- Don't annotate `__init__` return types (type checkers infer `None`)
68-
- Use explicit `return None` for functions with `-> Type | None` return type
69-
- Some Django-style ORM patterns are inherently difficult to type - that's okay
70-
- Goal is progress, not perfection
18+
## Scratch directory
7119

72-
Example workflow:
20+
Use the `scratch` directory for temporary files and experimentation. This directory is gitignored.
7321

74-
```bash
75-
# Check coverage
76-
uv run plain code annotations plain/plain/assets --details
22+
## Testing changes
7723

78-
# After adding annotations...
79-
./scripts/type-check plain/plain/assets
80-
./scripts/fix
81-
./scripts/test plain
82-
uv run plain code annotations plain/plain/assets # Should show 100%
83-
```
24+
The `example` directory contains a demo app. Use `cd example && uv run plain` to test.
8425

8526
## Coding style
8627

87-
- Don't include args and returns in docstrings if they are already type annotated.
88-
- CLI command docstrings should be concise, informative, no punctuation at the end.
89-
- Don't use overloaded terms. Where possible, prefer unique, specific, and greppable names.
90-
91-
## Verifying changes
92-
93-
Not everything needs a test, but be liberal about using `print()` statements to verify changes and show the before and after effects of your changes. Make sure those print statements are removed before committing your changes.
94-
95-
## Documentation
96-
97-
When writing documentation (READMEs, docstrings, etc.), follow the principles from [What Makes Documentation Good](https://github.com/openai/openai-cookbook/blob/main/articles/what_makes_documentation_good.md):
98-
99-
- Make docs easy to skim
100-
- Split content into sections with titles.
101-
- Prefer titles with informative sentences over abstract nouns.
102-
- Include a table of contents.
103-
- Keep paragraphs short.
104-
- Begin paragraphs and sections with short topic sentences that give a standalone preview.
105-
- Put topic words at the beginning of topic sentences.
106-
- Put the takeaways up front.
107-
- Use bullets and tables.
108-
- Bold important text.
109-
- Write well
110-
- Keep sentences simple.
111-
- Write sentences that can be parsed unambiguously.
112-
- Avoid left-branching sentences.
113-
- Avoid demonstrative pronouns (e.g., "this"), especially across sentences.
114-
- Be consistent.
115-
- Don't tell readers what they think or what to do.
116-
- Be broadly helpful
117-
- Write simply.
118-
- Avoid abbreviations.
119-
- Offer solutions to potential problems.
120-
- Prefer terminology that is specific and accurate.
121-
- Keep code examples general and exportable.
122-
- Prioritize topics by value.
123-
- Don't teach bad habits.
124-
- Introduce topics with a broad opening.
125-
- Break these rules when you have a good reason
126-
- "Documentation is an exercise in empathy."
28+
- Prefer unique, greppable names over overloaded terms
29+
- Verify changes with `print()` statements, then remove before committing

plain-code/plain/code/skills/plain-fix/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Automatically fixes formatting and linting issues using ruff and biome.
1515

1616
- Add `from __future__ import annotations` at the top of Python files
1717
- Keep imports at the top of the file unless avoiding circular imports
18+
- Don't include args/returns in docstrings if already type annotated
1819

1920
Options:
2021

plain/plain/cli/agent.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,15 @@ def _install_skills_to(
9898
installed_count = 0
9999
removed_count = 0
100100

101-
# Remove orphaned skills (exist in dest but not in source)
101+
# Remove orphaned plain-* skills (exist in dest but not in source)
102+
# Only remove skills with plain- prefix to preserve user-created skills
102103
if dest_skills_dir.exists():
103104
for dest_dir in dest_skills_dir.iterdir():
104-
if dest_dir.is_dir() and dest_dir.name not in source_skill_names:
105+
if (
106+
dest_dir.is_dir()
107+
and dest_dir.name.startswith("plain-")
108+
and dest_dir.name not in source_skill_names
109+
):
105110
shutil.rmtree(dest_dir)
106111
removed_count += 1
107112

0 commit comments

Comments
 (0)