Skill command extension
Makes pi recognize a skill command whose name and arguments are separated by a newline, instead of only a space.
pi expands /skill:name args by parsing the name up to the first space. An injected command whose name and arguments sit on separate lines - the shape the software factory's consultation templates use, where the command is the first line and the body below it - therefore fails the lookup: the parsed "name" is the name plus the newlines plus the start of the argument text, nothing matches, and the text passes through unexpanded. The model then sees a literal /skill: line and, for skills that carry disable-model-invocation: true (absent from the prompt's skills section), no pointer to the file at all.
Behavior
- On every submitted prompt, the extension checks the text. When it starts with
/skill:nameand the whitespace between the name and the arguments contains a newline, that separator becomes a single space. The arguments keep their remaining bytes; pi trims them when it expands, so the recorded message is what a space-separated command would have produced. - pi's built-in expansion runs on the normalized text. The lookup, the SKILL.md read, the frontmatter strip, and the recorded
<skill name=... location=...>block are all pi's; the extension never reads a SKILL.md and adds no setting. - Commands pi already parses (space separator, bare name) and all non-skill text pass through untouched. An unknown skill name with a newline separator is normalized but still fails pi's lookup and passes through, as before.
- A tab-only separator is out of scope: pi does not claim that shape either, and no producer injects it.
How it works
The rewrite is one pure function in the engine-free core module (extensions/skill-command/core.ts); the pi wiring (index.ts) registers a single handler on the input event, which fires on every submitted prompt before pi's own skill and template expansion. See ADR 0033.
Limitations
If pi changes how it expands skill commands - for example to accept newline separators natively - the rewrite becomes invisible: it produces the form pi parses today, which a more tolerant pi still parses. If pi changes the /skill: invocation syntax, the regex in the core module needs to follow.