nuskills
Prompt text about Nu and nuspace, in one place, tested against the current code.
- nuagent loads pieces into its system prompt.
- Outside agents (Claude Code, Codex) get skills built from the same pieces.
- Every fenced Python block in the corpus is built against the latest nucore, nustd and nuspace, so a piece cannot go stale without a red test.
Layout
src/nuskills/
__init__.py loader: pieces(), load(), read(), __version__
corpus/
nu/ the kernel: thesis, crashcourse, composition, ...
nustd/ fabrics: kv, mem, ui, ...
nuspace/ the space model, ops, snippets, drawing a cell
skills.py which pieces each built skill carries, in order
headers/ per skill SKILL.md frontmatter and a few lines of when-to-use
build.py assembles skills/ from headers + pieces
skills/ built skills, committed, never edited by hand
.claude-plugin/ plugin.json + marketplace.json: the repo is a Claude Code plugin
tests/ the block harness, the loader tests, the skills checks
Using it from Python
import nuskills
nuskills.pieces("nu") # ["nu/crashcourse", ...]
nuskills.read("nu/crashcourse") # markdown, frontmatter stripped
nuskills.load("nu/crashcourse") # Piece(id, title, summary, body)
Each consumer picks its pieces and decides their order. nuagent pins nuskills and assembles its system prompt from them, adding its own agent-specific text (role, protocol, finish) and the generated parts (the nu.inspect catalogue, the app surface). The pieces are package data, so importlib.resources.files("nuskills") / "corpus" / "nu" / "crashcourse.md" reaches the raw file too; the loader is the supported way.
Skills
A skill is a header plus an ordered list of pieces, defined in src/nuskills/skills.py:
| Skill | For |
|---|---|
nu |
building Nu programs and apps (kernel + nustd fabrics, kv, service, ui) |
nuspace |
programming a running nuspace (cell progs, ops, brackets, state, drawing, snippets) |
Each one is built in Claude Code's progressive disclosure layout. SKILL.md holds the header, a table of the reference files with each piece's summary, and the pieces every task needs (inline). The rest (reference) are files next to it, read only when the task needs one, so they cost no context until then. A piece's mention of another piece (nustd/ui-refs) becomes a link to wherever it landed.
skills/<name>/
SKILL.md
reference/<group>/<piece>.md
The skills carry no catalogue. They tell the agent to render the API with nu.inspect in its own environment, so a skill is right for whatever version is installed.
Rebuild after editing a piece, a header or skills.py, and commit the result. tests/test_skills.py fails while skills/ is out of date.
uv run python -m nuskills.build # write skills/
uv run python -m nuskills.build --check # exit 1 if skills/ is out of date
Installing in Claude Code
The repo is a plugin marketplace (nustack) holding one plugin (nuskills):
claude plugin marketplace add nustackdev/nuskills
claude plugin install nuskills@nustack
Inside a session, /plugin marketplace add nustackdev/nuskills then /plugin install nuskills@nustack do the same. The skills show up as /nuskills:nu and /nuskills:nuspace, and Claude also loads them on its own when a task matches their description. To try a local checkout without installing: claude --plugin-dir path/to/nuskills. Validate after editing the manifests: claude plugin validate ..
Writing a piece
A piece is one markdown file, corpus/<group>/<name>.md, its id is <group>/<name>. Keep it small enough to be picked on its own. Store only text that can't be generated: the catalogue (nu.inspect) and an app's surface are built at prompt time, never written here.
Optional frontmatter, title and summary only:
---
title: Crash course
summary: The ten things you write in every Nu program.
---
Fences
The info string on the opening fence says what the harness does with the block.
| Fence | Meaning | Checked by |
|---|---|---|
```python |
a whole program | loaded, out called, nu.validate(nu.compile(term)) |
```python run |
a whole program that finishes quickly in memory | the above, then evaluated with nu.arun (10s cap) |
```python fragment |
a few lines, not a program | Python compile() only |
anything else (text, bash, ...) |
prose | skipped |
Any other word after python fails the test, so a typo can't turn a program into prose.
A whole program is a module with an entry point out, loaded by nu.prog's own loader (the one nuspace uses for a cell):
outis a function returning a Nu term, or a term itself.outtakes only what its signature asks for, by name.- In
nu/andnustd/pieces nothing is offered: writedef out():. - In
nuspace/pieces the block is a cell program. It is stored as a cell on a plane in an in-memory space and loaded the way the kernel loads it.outmay ask forplaneandcell, the ids as plainstr.CellStateandPlaneStateslots land under that cell and plane. Store access needs its own bracket, as in a real cell (ops.atomic_state(...),ops.snapshot(...)). Arunblock runs inside the cell'sops.Hereframe against that space. There is no browser session, so a block that draws should not be markedrun. - A string literal in a block that contains
def out(is another program's source (eg the cell anops.add_celladds) and is built the same way, under the same group's rules.
Mark run only on programs that finish and touch nothing outside memory. A program that subscribes, waits or serves stays unmarked: built and validated, not run.
Checking a piece
uv sync # once: Python 3.10 .venv with the sibling repos editable
uv run pytest -k nuspace/model # every block in one piece
uv run pytest -k "nu/crashcourse:42" # one block: piece and the fence's line
uv run pytest # everything
uv run ruff check
Each block is its own test, id <piece>:<line>, the line of its opening fence, so a failure points at the exact block. The dev env installs ../nu, ../nu/pkgs/nustd[all], ../nuspace and ../nuverse/pkgs/nuverse editable, so it tests against main.
CI
.github/workflows/test.yml runs ruff, the skills check and pytest against two stacks: main (nu, nuspace and nuverse checked out next to this repo, as [tool.uv.sources] expects) and released (the latest nustd[all], nuspace, nuverse from PyPI). It runs on push and PR, nightly, by hand, and on a repository_dispatch (nu-release, nuspace-release, nuverse-release) a sibling release fires; the header of the workflow has the step a sibling adds.
Versions
nuskills versions on its own, not in step with nu. CI tests the corpus against both current main and the latest released stack, so a version only says what changed in the text. .claude-plugin/plugin.json carries the same version as pyproject.toml (a test checks it), so installed plugins update when it moves.
Release: bump version in pyproject.toml and .claude-plugin/plugin.json, rename the CHANGELOG's Unreleased heading to the version + date, commit and push, then git tag nuskills@X.Y.Z && git push origin nuskills@X.Y.Z. .github/workflows/publish.yml publishes to PyPI (trusted publisher) and cuts a GitHub Release.
Metadata
Release files for nuskills 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nuskills-0.2.0.tar.gz | 63.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nuskills-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 143.8 kB
Release files / nuskills-0.2.0.tar.gz
| Download URL | nuskills-0.2.0.tar.gz |
|---|---|
| Size | 63.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a2ac9e26884d74d1a68597d3a2c94a336ef484f6202b3ee6e5ea176bea6e79e
|
|
BLAKE2b-256 checksum How to use checksums |
757adc5acf3f98d5c618610466159d0cf7324e58e320a219556a2d2f96507608
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / nuskills-0.2.0-py3-none-any.whl
| Download URL | nuskills-0.2.0-py3-none-any.whl |
|---|---|
| Size | 80.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
96effe0dce6fce0d9736167104383862967c35ef458835c3fce8443de11da0ba
|
|
BLAKE2b-256 checksum How to use checksums |
e023304a4817f4326f021748d26b525254893e368af378eaa50b68cee00c5c3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log