From zush-skills
Use when the user wants to turn a Python package into a zush plugin — scaffolding a top-level `__zush__.py` ZUSH manifest with commands (and optionally hooks/services), writing the typed target functions, and indexing them with `zush rebuild`.
How this skill is triggered — by the user, by Claude, or both
Slash command
/zush-skills:create-zush-packageThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A Python package becomes a zush plugin by shipping a `__zush__.py` manifest at its
A Python package becomes a zush plugin by shipping a __zush__.py manifest at its
top level. zush rebuild finds it, reads each target's function signature, and bakes
everything into ~/.zush/pyindex.json. At dispatch, zush imports only the one target
module and calls the function. You never import or decorate anything from zush.
Canonical reference (read for anything below not covered here):
Confirm the package layout. There must be an importable package directory
(the folder with __init__.py, or an installed distribution). The manifest goes at
that package's top level: mypkg/__zush__.py.
Write the manifest as a single module-level ZUSH dict. All three sections are
optional; most plugins start with just commands. Nesting maps to dotted command
paths; leaves are "relative/path.py::function" targets, relative to the package dir:
ZUSH = {
"commands": {
"git": { # nesting -> dotted path
"clean": "ops/git.py::clean", # -> zush git.clean
"sync": "ops/git.py::sync", # -> zush git.sync
},
},
}
Write the target functions as normal typed functions — no decorators.
mypkg/ops/git.py:
def clean(path: str, force: bool = False):
return f"clean {path} (force={force})"
def sync():
return "synced"
The return value, if any, is printed.
Make the package importable, then index and run:
pip install -e . # or: uv pip install -e .
zush rebuild # writes ~/.zush/pyindex.json
zush git.clean ./tmp --force
zush git.sync
zush reads each target's signature at rebuild time. Shape the signature to shape the CLI:
| Parameter shape | Becomes |
|---|---|
| no default (required) | a positional argument |
| has a default | an option --name |
bool default | a flag (present = True) |
int / float / str typed | value coerced to that type |
parameter named ctx | injected service context, not a CLI argument |
*args / **kwargs | ignored by the parser |
So def migrate(target: str, steps: int = 1, dry_run: bool = False) is run as
zush db.migrate head --steps 3 --dry-run.
Add to the same ZUSH dict when needed — distinct concerns, scaffold only what is asked:
hooks: pre/post/error with [] wildcards —
https://github.com/ZackaryW/zush/blob/main/docs/hooks.mdservices: shared ctx injected into ctx-named params —
https://github.com/ZackaryW/zush/blob/main/docs/services.mdzush rebuild prints a collision warning. Pick a unique top-level namespace.zush rebuild after installing or changing the plugin.ZUSH_PATH and ZUSH_INDEX (useful for
testing against an isolated plugin set).Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub zackaryw/zush-skills --plugin zush-skills