关于 template-renderer
template-renderer 是用于填充规格、计划和任务模板的 Skill,面向生成 Markdown 文档的工作流,并提供令牌、路径及架构检查。
主要功能
- 01渲染规格、计划和任务模板
- 02替换 {{TOKEN}} 占位符
- 03校验令牌白名单并清理输入
- 04验证模板与输出路径
- 05检查规格模板架构
- 06提示缺失及未使用的令牌
适用场景
- 01根据收集的需求生成规格文档
- 02通过令牌值创建项目计划
- 03使用经过验证的模板数据生成任务文档
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill template-renderer安装后在 Claude Code 中输入/template-renderer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
commands/template-renderer.mdhooks/post-execute.cjspre-execute.cjsreferences/research-requirements.mdrules/template-renderer.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md详细介绍
模板渲染器
模板渲染器技能 - 通过将 {{TOKEN}} 占位符替换为实际值来渲染模板。支持 specification-template.md、plan-template.md 和 tasks-template.md,并提供架构验证和安全控制(SEC-SPEC-003、SEC-SPEC-004)。 - 渲染所有三种模板类型(specification、plan、tasks) - 替换令牌:将 {{TOKEN}} 替换为对应值 - 安全:对令牌值进行清理(防止注入) - 安全:强制执行令牌白名单(仅允许预定义令牌) - 安全:验证模板路径(仅限 PROJECT_ROOT) - 验证 specification 模板的架构 - 处理缺少必需令牌的错误 - 为未使用的令牌提供警告 - 保留 Markdown 格式和结构步骤 1:验证输入(安全 - 必须执行)
模板路径验证(SEC-SPEC-002):
- 确认模板文件位于 PROJECT_ROOT 内
- 拒绝任何路径遍历尝试(../)
- 仅允许使用
.claude/templates/中的模板
令牌白名单验证(SEC-SPEC-003):
// Allowed tokens by template type
const SPEC_TOKENS = [
'FEATURE_NAME',
'VERSION',
'AUTHOR',
'DATE',
'STATUS',
'ACCEPTANCE_CRITERIA_1',
'ACCEPTANCE_CRITERIA_2',
'ACCEPTANCE_CRITERIA_3',
'TERM_1',
'TERM_2',
'TERM_3',
'HTTP_METHOD',
'ENDPOINT_PATH',
'PROJECT_NAME',
];
const PLAN_TOKENS = [
'PLAN_TITLE',
'DATE',
'FRAMEWORK_VERSION',
'STATUS',
'EXECUTIVE_SUMMARY',
'TOTAL_TASKS',
'FEATURES_COUNT',
'ESTIMATED_TIME',
'STRATEGY',
'KEY_DELIVERABLES_LIST',
'PHASE_N_NAME',
'PHASE_N_PURPOSE',
'PHASE_N_DURATION',
'DEPENDENCIES',
'PARALLEL_OK',
'VERIFICATION_COMMANDS',
];
const TASKS_TOKENS = [
'FEATURE_NAME',
'VERSION',
'AUTHOR',
'DATE',
'STATUS',
'PRIORITY',
'ESTIMATED_EFFORT',
'RELATED_SPECS',
'DEPENDENCIES',
'FEATURE_DISPLAY_NAME',
'FEATURE_DESCRIPTION',
'BUSINESS_VALUE',
'USER_IMPACT',
'EPIC_NAME',
'EPIC_GOAL',
'SUCCESS_CRITERIA',
];
令牌值清理(SEC-SPEC-004):
function sanitizeTokenValue(value) {
return String(value)
.replace(/[<>]/g, '') // Prevent HTML injection
.replace(/\$\{/g, '') // Prevent template literal injection
.replace(/\{\{/g, '') // Prevent nested token injection
.trim();
}
步骤 2:读取模板
使用 Read 或 mcpfilesystemread_text_file 读取模板文件:
.claude/templates/specification-template.md(46 个令牌).claude/templates/plan-template.md(30 个以上令牌).claude/templates/tasks-template.md(20 个以上令牌)
步骤 3:替换令牌
将所有 {{TOKEN}} 占位符替换为经过清理的值:
function renderTemplate(templateContent, tokenMap) {
let rendered = templateContent;
// Replace each token
for (const [token, value] of Object.entries(tokenMap)) {
// Validate token is in whitelist
if (!isAllowedToken(token, templateType)) {
throw new Error(`Token not in whitelist: ${token}`);
}
// Sanitize value
const sanitizedValue = sanitizeTokenValue(value);
// Replace all occurrences
const regex = new RegExp(`\\{\\{${token}\\}\\}`, 'g');
rendered = rendered.replace(regex, sanitizedValue);
}
// Check for missing required tokens
const missingTokens = rendered.match(/\{\{[A-Z_0-9]+\}\}/g);
if (missingTokens) {
throw new Error(`Missing required tokens: ${missingTokens.join(', ')}`);
}
return rendered;
}
步骤 4:架构验证(仅限 Specification 模板)
对于 specification 模板,使用 JSON Schema 验证渲染后的输出:
// Extract YAML frontmatter
const yamlMatch = rendered.match(/^---\n([\s\S]*?)\n---/);
if (!yamlMatch) {
throw new Error('No YAML frontmatter found');
}
// Parse YAML
const yaml = require('js-yaml');
const frontmatter = yaml.load(yamlMatch[1]);
// Validate against schema
const schema = JSON.parse(
fs.readFileSync('.claude/schemas/specification-template.schema.json', 'utf8')
);
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(schema);
if (!validate(frontmatter)) {
throw new Error(`Schema validation failed: ${JSON.stringify(validate.errors)}`);
}
步骤 5:写入输出
使用 Write 或 mcpfilesystemwrite_file 将渲染后的模板写入输出路径:
- 确认输出路径位于 PROJECT_ROOT 内
- 如有需要,创建父目录
- 使用 UTF-8 编码写入文件
步骤 6:验证
运行渲染后的检查:
# Check no unresolved tokens remain
grep "{{" <output-file> && echo "ERROR: Unresolved tokens found!" || echo "✓ All tokens resolved"
# For specifications: Validate YAML frontmatter
head -50 <output-file> | grep -E "^---$" | wc -l # Should output: 2
# For specifications: Validate against schema (if ajv installed)
# ajv validate -s .claude/schemas/specification-template.schema.json -d <output-file>
</execution_process>
<best_practices>
- 始终验证模板路径:读取前使用 PROJECT_ROOT 验证
- 清理所有令牌值:防止注入攻击(SEC-SPEC-004)
- 强制执行令牌白名单:仅允许预定义令牌(SEC-SPEC-003)
- 缺少令牌时出错:不要静默忽略缺少的必需令牌
- 警告未使用的令牌:帮助用户发现令牌名称中的拼写错误
- 保留 Markdown 格式:不要更改缩进、项目符号和代码块
- 验证规格的架构:对 specification 模板运行 JSON Schema 验证
- 记录所有操作:将模板、使用的令牌和输出路径记录到记忆中
</best_practices>
<error_handling>
缺少必需令牌:
ERROR: Missing required tokens in template:
- {{FEATURE_NAME}}
- {{ACCEPTANCE_CRITERIA_1}}
Provide these tokens in the token map.
无效令牌(不在白名单中):
ERROR: Token not in whitelist: INVALID_TOKEN
Allowed tokens for specification-template: FEATURE_NAME, VERSION, AUTHOR, DATE, ...
模板路径遍历:
ERROR: Template path outside PROJECT_ROOT
Path: ../../etc/passwd
Only templates from .claude/templates/ are allowed.
架构验证失败(Specification 模板):
ERROR: Schema validation failed:
- /version: must match pattern "^\d+\.\d+\.\d+$"
- /acceptance_criteria: must have at least 1 item
未使用令牌警告:
WARNING: Unused tokens provided:
- EXTRA_TOKEN_1
- EXTRA_TOKEN_2
These tokens are not in the template. Check for typos.
</error_handling>
**示例 1:渲染 Specification 模板**// From another skill (e.g., spec-gathering)
Skill({
skill: 'template-renderer',
args: {
templateName: 'specification-template',
outputPath: '.claude/context/artifacts/specifications/my-feature-spec.md',
tokens: {
FEATURE_NAME: 'User Authentication',
VERSION: '1.0.0',
AUTHOR: 'Claude',
DATE: '2026-01-28',
STATUS: 'draft',
ACCEPTANCE_CRITERIA_1: 'User can log in with email and password',
ACCEPTANCE_CRITERIA_2: 'Password meets complexity requirements',
ACCEPTANCE_CRITERIA_3: 'Failed login attempts are logged',
},
},
});
示例 2:渲染 Plan 模板
Skill({
skill: 'template-renderer',
args: {
templateName: 'plan-template',
outputPath: '.claude/context/plans/my-feature-plan.md',
tokens: {
PLAN_TITLE: 'User Authentication Implementation Plan',
DATE: '2026-01-28',
FRAMEWORK_VERSION: 'Agent-Studio v3.1.0',
STATUS: 'Phase 0 - Research',
EXECUTIVE_SUMMARY: 'Implementation plan for JWT-based authentication...',
TOTAL_TASKS: '14 atomic tasks',
ESTIMATED_TIME: '2-3 weeks',
STRATEGY: 'Foundation-first (schema) → Core features',
},
},
});
示例 3:渲染 Tasks 模板
Skill({
skill: 'template-renderer',
args: {
templateName: 'tasks-template',
outputPath: '.claude/context/artifacts/tasks/auth-tasks.md',
tokens: {
FEATURE_NAME: 'user-authentication',
VERSION: '1.0.0',
AUTHOR: 'Engineering Team',
DATE: '2026-01-28',
FEATURE_DISPLAY_NAME: 'User Authentication',
FEATURE_DESCRIPTION: 'JWT-based authentication system',
BUSINESS_VALUE: 'Enables user account management',
USER_IMPACT: 'Users can securely access personalized features',
},
},
});
示例 4:CLI 用法
# Using CLI wrapper (after implementation in main.cjs)
node .claude/skills/template-renderer/scripts/main.cjs \
--template specification-template \
--output ./my-spec.md \
--tokens '{"FEATURE_NAME":"My Feature","VERSION":"1.0.0","AUTHOR":"Claude","DATE":"2026-01-28"}'
# Or with JSON file
node .claude/skills/template-renderer/scripts/main.cjs \
--template plan-template \
--output ./my-plan.md \
--tokens-file ./tokens.json
示例 5:与 spec-gathering 集成
// In spec-gathering skill (Task #16):
// After collecting requirements via progressive disclosure...
const tokens = {
FEATURE_NAME: gatheredRequirements.featureName,
VERSION: '1.0.0',
AUTHOR: 'Claude',
DATE: new Date().toISOString().split('T')[0],
ACCEPTANCE_CRITERIA_1: gatheredRequirements.criteria[0],
ACCEPTANCE_CRITERIA_2: gatheredRequirements.criteria[1],
ACCEPTANCE_CRITERIA_3: gatheredRequirements.criteria[2],
// ... more tokens
};
Skill({
skill: 'template-renderer',
args: {
templateName: 'specification-template',
outputPath: `.claude/context/artifacts/specifications/${featureName}-spec.md`,
tokens: tokens,
},
});
</usage_example>
记忆协议(必须遵守)
开始前:
cat .claude/context/memory/learnings.md
完成后:
- 新模式 ->
.claude/context/memory/learnings.md - 发现问题 ->
.claude/context/memory/issues.md - 做出决策 ->
.claude/context/memory/decisions.md
假设任务会中断:你的上下文可能会重置。如果没有记录在记忆中,就等于没有发生。
评论
支持 Markdown