refactor: mirror module namespaces to their directories (task 0031)
Adopt the convention that a Module's option path mirrors its directory under modules/, with an index file naming the directory's own segment. - Group agent Modules under modules.agents.*: claude-code (whole directory), pi (flattened to a file), skills (renamed from agent-skills), and gitea-axi under an agents/tools/ subgroup. The agents/ and tools/ folders are pure namespace prefixes with no aggregator enable. - Nest hypridle and hyprlock under modules.desktop.hyprland.*, with hyprland.nix as the index, and update the desktop aggregator. - Remove the obsolete example Module. - Record the convention in CONTEXT.md and ADR 0004, and update the neogaia host, the two live CLAUDE.md gotchas, and the skills Module's intentional Enable-convention exception comment.
This commit was merged in pull request #23.
This commit is contained in:
152
modules/agents/claude-code/skills/library/nbdev/SKILL.md
Normal file
152
modules/agents/claude-code/skills/library/nbdev/SKILL.md
Normal file
@@ -0,0 +1,152 @@
|
||||
---
|
||||
name: nbdev
|
||||
description: nbdev conventions for notebooks — directives, cell structure, docments, tests, execution. Use for any .ipynb operation — including reads — in an nbdev project.
|
||||
---
|
||||
|
||||
# nbdev
|
||||
|
||||
## Tool Preference
|
||||
|
||||
- Use the **Jupyter MCP** for all `.ipynb` operations — read, edit, insert, delete, execute
|
||||
- Do **not** use the built-in `NotebookEdit` tool; it writes cell source as a single JSON string which breaks standard Jupyter formatting and produces noisy diffs
|
||||
- Re-read the notebook before editing if it may have changed since your last read — cell indices/IDs can shift under concurrent edits (e.g. via JupyterLab's real-time collaboration), and editing by a stale index can hit the wrong cell
|
||||
|
||||
## nbdev Directives
|
||||
|
||||
Directives are comments at the top of a cell that control how nbdev processes it:
|
||||
|
||||
- `#| export` — include this cell in the exported Python module and in the docs
|
||||
- `#| hide` — exclude this cell from both the module and the docs
|
||||
- `#| hide_input` — show cell output in docs but hide the source code
|
||||
- `#| default_exp module_name` — set which module this notebook exports to (second cell)
|
||||
- `#| exporti` — export to module but do not show in docs (for internal helpers)
|
||||
- `#| eval: false` — include in docs but do not execute during `nbdev-test`
|
||||
|
||||
Imports needed only for tests or examples should **not** be exported.
|
||||
|
||||
Never hand-edit the exported `.py` module files — they're build artifacts regenerated from the notebook by `nbdev_export`. All edits go through the source notebook in `nbs/`.
|
||||
|
||||
## Notebook Structure
|
||||
|
||||
Every notebook must follow this structure:
|
||||
|
||||
**Cell 1 — Markdown frontmatter:**
|
||||
```markdown
|
||||
# Module Title
|
||||
|
||||
> A one-line description of what this module does
|
||||
```
|
||||
The H1 becomes the page title in docs. The blockquote becomes the subtitle.
|
||||
|
||||
**Cell 2 — Default export:**
|
||||
```python
|
||||
#| default_exp module_name
|
||||
```
|
||||
|
||||
**Body cells** — alternating between exported code, demonstrations, and markdown explanations (see Cell Structure below).
|
||||
|
||||
**Last cell:**
|
||||
```python
|
||||
#| hide
|
||||
import nbdev; nbdev.nbdev_export()
|
||||
```
|
||||
|
||||
Before declaring any notebook task complete, restart the kernel and run all cells top-to-bottom to verify it is fully reproducible.
|
||||
|
||||
## Cell Structure
|
||||
|
||||
Keep cells short. Each exported function gets its own cell, immediately followed by a demonstration. Do not write long functions with comments interspersed — split them into small separate cells with explanations and working examples after each.
|
||||
|
||||
The pattern per concept:
|
||||
|
||||
1. *(Optional)* A markdown cell explaining what comes next
|
||||
2. A `#| export` code cell with the function
|
||||
3. One or more plain code cells demonstrating usage
|
||||
4. Assertions that double as tests
|
||||
|
||||
Example:
|
||||
```python
|
||||
#| export
|
||||
def slugify(text: str) -> str:
|
||||
"Convert text to a URL-safe slug"
|
||||
return re.sub(r"[^a-z0-9]+", "-", text.lower()).strip("-")
|
||||
```
|
||||
```python
|
||||
slug = slugify("Hello, World!")
|
||||
assert slug == "hello-world"
|
||||
slug
|
||||
```
|
||||
|
||||
## Docstrings and Parameter Documentation
|
||||
|
||||
Keep docstrings short — a single-line summary is sufficient for most functions. Elaborate in separate markdown or code cells below, where you can use real examples.
|
||||
|
||||
Use **docments** (inline parameter comments) instead of verbose docstring parameter sections:
|
||||
|
||||
```python
|
||||
#| export
|
||||
def greet(
|
||||
name: str, # Person to greet
|
||||
greeting: str="Hi", # Greeting word to use
|
||||
) -> str: # The composed greeting
|
||||
"Compose a greeting for name"
|
||||
return f"{greeting}, {name}!"
|
||||
```
|
||||
|
||||
This renders as a clean parameter table in the docs automatically — no need to repeat type information in the docstring body.
|
||||
|
||||
Use backticks around symbol names in docstrings and markdown — nbdev automatically converts these to hyperlinks to the relevant reference page.
|
||||
|
||||
## Code Style
|
||||
|
||||
- **Prefer composition**: write small functions that do one thing well
|
||||
- Each exported function should be focused enough to fit naturally in a single notebook cell — one cell, one idea
|
||||
- Use type hints on all exported functions
|
||||
- Avoid classes unless state is genuinely needed — prefer functions that take and return data
|
||||
- If you do write a class, use `fastcore`'s `@patch` decorator to define each method in its own cell, immediately followed by a demonstration. This avoids long class definitions and keeps examples close to the code
|
||||
|
||||
When a class is needed, document its methods with `show_doc`:
|
||||
```python
|
||||
from nbdev.showdoc import show_doc
|
||||
show_doc(MyClass.my_method)
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Every code cell is run as a test by nbdev unless explicitly marked otherwise — any exception fails the test.
|
||||
|
||||
- Turn demonstrations into tests by adding `assert` statements
|
||||
- Use `fastcore.test` helpers for better error messages:
|
||||
```python
|
||||
from fastcore.test import test_eq, test_fail
|
||||
test_eq(slugify("Hello World"), "hello-world")
|
||||
```
|
||||
- Document expected error cases with `test_fail`:
|
||||
```python
|
||||
test_fail(lambda: slugify(""), contains="empty")
|
||||
```
|
||||
- Each test/demo cell should import what it needs directly — don't rely on a name imported in a later cell just because it happened to be in scope during a prior run
|
||||
|
||||
## Execution
|
||||
|
||||
- Always execute cells after writing them to verify they work
|
||||
- If a cell errors, read the full traceback before attempting a fix — do not guess
|
||||
- When installing packages, use `%pip install` inside the notebook (not `!pip install`) so they install into the running kernel
|
||||
- Use autoreload at the top of notebooks that import from other modules in the project:
|
||||
```python
|
||||
%load_ext autoreload
|
||||
%autoreload 2
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- Use H2 (`##`) markdown cells to group related symbols within a notebook
|
||||
- Use H4 (`####`) markdown cells to split long explanations within a symbol's section (notes, examples, edge cases, etc.)
|
||||
- Add rich representations to classes via `_repr_markdown_` where it aids understanding
|
||||
- Include real code examples, plots, and diagrams — notebooks support rich output, use it
|
||||
|
||||
## Outputs
|
||||
|
||||
- Never print secrets, tokens, passwords, or API keys into cell output — notebook outputs get committed to git and published in docs, unlike transient script output
|
||||
- Prefer summaries over dumping large data structures (`.head()`, `len()`, `[:5]`, etc.)
|
||||
- Large outputs consume context window — keep them concise
|
||||
Reference in New Issue
Block a user