pub fn render(
template: &SkillTemplate,
branch: &str,
broker_url: &str,
project: &str,
gates: &GateCommands<'_>,
backends: &[SpecBackendKind],
) -> StringExpand description
Renders a skill template for a specific worktree.
Substitutes the following placeholders at render time:
{{BRANCH_ID}}— the slugified branch name (feat/foo→feat-foo){{PROJECT_NAME}}— the project name (e.g."git-paw"), used in thepaw-{{PROJECT_NAME}}tmux session name{{GIT_PAW_BROKER_URL}}— the fully-qualified broker URL, pre-expanded here so the agent’s curl commands contain a literal URL and no shell expansion is needed at execution time. Pre-expanding at render time is important: some CLI tools gate shell-variable expansion behind extra permission prompts, which breaks the “don’t ask again forcurl:*” allowlist flow.{{TEST_COMMAND}}— the supervisor’s configuredtest_command(e.g."just check"). Whentest_commandisNone, the placeholder substitutes to the literal"(not configured)"so the rendered prose stays readable.{{LINT_COMMAND}},{{BUILD_COMMAND}},{{DOC_BUILD_COMMAND}},{{SPEC_VALIDATE_COMMAND}},{{FMT_CHECK_COMMAND}},{{SECURITY_AUDIT_COMMAND}}— the five additional gate commands from[supervisor]config.Nonerenders as(not configured), identical to{{TEST_COMMAND}}behaviour.
{{CHANGE_ID}} is not substituted here. The spec-validate command
typically embeds {{CHANGE_ID}} as a per-invocation placeholder that
the supervisor agent expands at verification time using the change name
being audited. Substituting it at render time would freeze the rendered
skill to a single change, which is wrong — the supervisor verifies
many changes over a session lifetime.
§Language-agnostic supervisor placeholders
Three additional placeholders make the bundled supervisor skill render correctly across language stacks without forking the template per language family:
{{DOC_TOOL_COMMAND}}— substitutes[supervisor].doc_tool_commandfrom config. Renders as the empty string when unset (the template prose is authored to read naturally without it; this avoids a stray(not configured)in places where empty reads fine).{{DEV_ALLOWLIST_PRESET}}— substitutes a prose enumeration of every entry inDEV_ALLOWLIST_PRESET, generated from the constant so adding new entries does not require a skill-template edit. Seerender_dev_allowlist_preset.{{SPEC_PATH_DOCTRINE}}— substitutes a per-backend path doctrine paragraph derived from thebackendsslice. Sessions resolving no backend render a sentinel sentence; multi-backend sessions render a paragraph listing each present backend’s path conventions. Seerender_spec_path_doctrine.
The backends parameter is the session’s resolved spec backends
(typically derived from SpecEntry.backend across the session’s
scan_specs(...) result). For non-supervisor renders or sessions
without resolved specs, pass &[] and the doctrine placeholder
renders its sentinel.
Any remaining {{...}} placeholder after substitution is logged as a
warning to stderr but does not cause render to fail. The
{{CHANGE_ID}} form is whitelisted from this warning since the spec
expects it to survive intact (see the agent-skills spec delta).
For standardized skills, additional metadata placeholders may be available:
{{SKILL_NAME}}— the skill name from metadata{{SKILL_DESCRIPTION}}— the skill description from metadata