refactor(skills): use PEP 723 inline deps + uv run for resolver
BMB standard and Anthropic's Agent Skills spec both reference the PEP 723 + uv pattern: declare dependencies in an inline script header, invoke via `uv run` so deps auto-install into a cached isolated environment on first run. - resolve_customization.py: add PEP 723 header declaring pyyaml>=6.0 and requires-python>=3.10. - Remove src/scripts/requirements.txt (superseded by inline metadata). - Update 6 agent SKILL.md files to invoke `uv run` instead of `python3`. - Update docs/how-to/customize-bmad.md to explain the uv requirement and the PEP 723 pattern, with a plain-python3 fallback note. - Refresh the script's ImportError message to point at uv run first.
This commit is contained in:
parent
da5016d34a
commit
6a5b814881
|
|
@ -183,31 +183,35 @@ agent:
|
||||||
|
|
||||||
## How Resolution Works
|
## How Resolution Works
|
||||||
|
|
||||||
On activation, the agent's SKILL.md runs a shared Python script that does the three-layer merge and returns the resolved `agent` block as JSON. The script requires Python 3.8+ and PyYAML (`pip install PyYAML`).
|
On activation, the agent's SKILL.md runs a shared Python script that does the three-layer merge and returns the resolved `agent` block as JSON. The script uses [PEP 723 inline script metadata](https://peps.python.org/pep-0723/) to declare its dependency on PyYAML, and is designed to be invoked via [`uv`](https://docs.astral.sh/uv/):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
uv run {project-root}/_bmad/scripts/resolve_customization.py \
|
||||||
--skill {skill-root} \
|
--skill {skill-root} \
|
||||||
--key agent
|
--key agent
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`uv run` reads the inline metadata, creates a cached isolated environment with PyYAML installed, and runs the script. First run takes a few seconds while the env is built; subsequent runs reuse the cache and are instant.
|
||||||
|
|
||||||
|
**Requirements**: Python 3.10+ and `uv` (install via `brew install uv`, `pip install uv`, or [the official installer](https://docs.astral.sh/uv/getting-started/installation/)). If `uv` isn't available, the script can be run with plain `python3` provided PyYAML is already installed (`pip install PyYAML`).
|
||||||
|
|
||||||
`--skill` points at the skill's installed directory (where `customize.yaml` lives). The skill name is derived from the directory's basename, and the script looks up `_bmad/custom/{skill-name}.yaml` and `{skill-name}.user.yaml` automatically.
|
`--skill` points at the skill's installed directory (where `customize.yaml` lives). The skill name is derived from the directory's basename, and the script looks up `_bmad/custom/{skill-name}.yaml` and `{skill-name}.user.yaml` automatically.
|
||||||
|
|
||||||
Useful invocations:
|
Useful invocations:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Resolve the full agent block
|
# Resolve the full agent block
|
||||||
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
uv run {project-root}/_bmad/scripts/resolve_customization.py \
|
||||||
--skill /abs/path/to/bmad-agent-pm \
|
--skill /abs/path/to/bmad-agent-pm \
|
||||||
--key agent
|
--key agent
|
||||||
|
|
||||||
# Resolve a single field
|
# Resolve a single field
|
||||||
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
uv run {project-root}/_bmad/scripts/resolve_customization.py \
|
||||||
--skill /abs/path/to/bmad-agent-pm \
|
--skill /abs/path/to/bmad-agent-pm \
|
||||||
--key agent.metadata.name
|
--key agent.metadata.name
|
||||||
|
|
||||||
# Full dump (everything under agent plus any other top-level keys)
|
# Full dump (everything under agent plus any other top-level keys)
|
||||||
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
uv run {project-root}/_bmad/scripts/resolve_customization.py \
|
||||||
--skill /abs/path/to/bmad-agent-pm
|
--skill /abs/path/to/bmad-agent-pm
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: Strategic business analyst and requirements expert. Use when the us
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: Technical documentation specialist and knowledge curator. Use when
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: Product manager for PRD creation and requirements discovery. Use wh
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: UX designer and UI specialist. Use when the user asks to talk to Sa
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: System architect and technical design leader. Use when the user ask
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ description: Senior software engineer for story execution and code implementatio
|
||||||
|
|
||||||
### Step 1: Resolve the Agent Block
|
### Step 1: Resolve the Agent Block
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
|
||||||
|
|
||||||
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
**If the script fails**, resolve the `agent` block yourself from `customize.yaml`, with `{project-root}/_bmad/custom/{skill-name}.yaml` overriding, and `{skill-name}.user.yaml` overriding both (any missing file is skipped).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
PyYAML>=6.0
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.10"
|
||||||
|
# dependencies = ["pyyaml>=6.0"]
|
||||||
|
# ///
|
||||||
"""
|
"""
|
||||||
Resolve customization for a BMad skill using three-layer YAML merge.
|
Resolve customization for a BMad skill using three-layer YAML merge.
|
||||||
|
|
||||||
|
|
@ -11,10 +15,12 @@ Skill name is derived from the basename of the skill directory.
|
||||||
|
|
||||||
Outputs merged JSON to stdout. Errors go to stderr.
|
Outputs merged JSON to stdout. Errors go to stderr.
|
||||||
|
|
||||||
Usage:
|
Dependencies declared inline via PEP 723. Invoke with `uv run` to
|
||||||
python3 resolve_customization.py --skill /abs/path/to/skill-dir
|
auto-install PyYAML into an isolated, cached environment:
|
||||||
python3 resolve_customization.py --skill ... --key agent
|
|
||||||
python3 resolve_customization.py --skill ... --key agent --key agent.menu
|
uv run resolve_customization.py --skill /abs/path/to/skill-dir
|
||||||
|
uv run resolve_customization.py --skill ... --key agent
|
||||||
|
uv run resolve_customization.py --skill ... --key agent --key agent.menu
|
||||||
|
|
||||||
Merge rules (matches BMad v6.1 semantics where applicable):
|
Merge rules (matches BMad v6.1 semantics where applicable):
|
||||||
- metadata: shallow merge (scalar fields override)
|
- metadata: shallow merge (scalar fields override)
|
||||||
|
|
@ -25,8 +31,6 @@ Merge rules (matches BMad v6.1 semantics where applicable):
|
||||||
- other tables: deep merge
|
- other tables: deep merge
|
||||||
- other arrays: atomic replace
|
- other arrays: atomic replace
|
||||||
- scalars: override wins
|
- scalars: override wins
|
||||||
|
|
||||||
Requires PyYAML. Install with: pip install PyYAML
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
@ -39,7 +43,9 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
"error: PyYAML is required to run this script.\n"
|
"error: PyYAML is required to run this script.\n"
|
||||||
"Install it with: pip install PyYAML\n"
|
"Invoke via `uv run resolve_customization.py ...` so dependencies\n"
|
||||||
|
"declared in the PEP 723 header are auto-installed, or run\n"
|
||||||
|
"`pip install PyYAML` if invoking with plain `python3`.\n"
|
||||||
)
|
)
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue