Skip to main content

render

Function render 

Source
pub fn render(
    template: &SkillTemplate,
    branch: &str,
    broker_url: &str,
    project: &str,
    gates: &GateCommands<'_>,
    backends: &[SpecBackendKind],
) -> String
Expand description

Renders a skill template for a specific worktree.

Substitutes the following placeholders at render time:

  • {{BRANCH_ID}} — the slugified branch name (feat/foofeat-foo)
  • {{PROJECT_NAME}} — the project name (e.g. "git-paw"), used in the paw-{{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 for curl:*” allowlist flow.
  • {{TEST_COMMAND}} — the supervisor’s configured test_command (e.g. "just check"). When test_command is None, 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. None renders 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_command from 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 in DEV_ALLOWLIST_PRESET, generated from the constant so adding new entries does not require a skill-template edit. See render_dev_allowlist_preset.
  • {{SPEC_PATH_DOCTRINE}} — substitutes a per-backend path doctrine paragraph derived from the backends slice. Sessions resolving no backend render a sentinel sentence; multi-backend sessions render a paragraph listing each present backend’s path conventions. See render_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