Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,13 @@ rolecraft knows where each AI agent looks for skills. When you use a flag like `
- **jazz:** jazz-ai (lvndry/jazz, not an AWS product); also reads project ./skills
- **iflow:** iFlow CLI was shut down on 2026-04-17; the vendor directs users to migrate to Qoder
- **lingma:** Also reads project .lingma/skills; renamed to Qoder CN on 2026-05-20
- **zcode:** ZCode, the GLM coding client. Reads ~/.zcode/skills/<name>/SKILL.md and ~/.agents/mcp.json
- **zcode:** ZCode, the GLM coding client. Reads ~/.zcode/skills/&lt;name&gt;/SKILL.md and ~/.agents/mcp.json
- **pochi:** Pochi (TabbyML). Also reads ~/.agents/skills; project .pochi/skills
- **chatgpt:** ChatGPT/Codex share the .agents skills locations; symlinked skill folders honored
- **amp:** amp skill add --global installs to ~/.config/agents/skills; also reads ~/.agents/skills
- **antigravity:** Antigravity 2.0 and the IDE read ~/.gemini/config/skills; the IDE also accepts legacy ~/.gemini/antigravity/skills. All surfaces share <workspace>/.agents/skills
- **antigravity-cli:** Antigravity CLI (agy) has its own global dir, separate from the 2.0/IDE surface; plugin skills at ~/.gemini/antigravity-cli/plugins/<name>/skills. Shares <workspace>/.agents/skills
- **grok:** Project skills at ./.grok/skills. Reads ~/.agents/skills via AGENTS.md compatibility. MCP lives in ~/.grok/config.toml as [mcp_servers.<name>] (TOML), which rolecraft does not yet write
- **antigravity:** Antigravity 2.0 and the IDE read ~/.gemini/config/skills; the IDE also accepts legacy ~/.gemini/antigravity/skills. All surfaces share &lt;workspace&gt;/.agents/skills
- **antigravity-cli:** Antigravity CLI (agy) has its own global dir, separate from the 2.0/IDE surface; plugin skills at ~/.gemini/antigravity-cli/plugins/&lt;name&gt;/skills. Shares &lt;workspace&gt;/.agents/skills
- **grok:** Project skills at ./.grok/skills. Reads ~/.agents/skills via AGENTS.md compatibility. MCP lives in ~/.grok/config.toml as [mcp_servers.&lt;name&gt;] (TOML), which rolecraft does not yet write
- **muse-code:** Muse Code by Meta. Scans ~/.config/muse/skills, ~/.agents/skills, ~/.claude/skills, ~/.codex/skills and project .agents/.codex/.claude/skills. MCP at ~/.config/muse/settings.json under mcpServers
- **posit-assistant:** Posit Assistant (Positron, RStudio). Also reads ~/.agents/skills; project .posit/assistant/skills. Legacy ~/.positai/
- **replit:** Project-committed .agents/skills only; no user-global skills dir
Expand Down
14 changes: 13 additions & 1 deletion scripts/generate-agents-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ function formatMcp(agent) {
return agent.mcpSupport.format
}

/**
* Agent notes carry literal paths like `~/.zcode/skills/<name>/SKILL.md`.
* Markdown-in-`<...>` is read as a Vue tag when VitePress builds the docs,
* and an unclosed one aborts the whole build, so angle brackets are escaped
* here rather than relying on every future note to avoid them.
*/
function escapeMarkdown(text) {
return text.replace(/</g, '&lt;').replace(/>/g, '&gt;')
}

/**
* Generate docs/agents.md content from manifest data
*/
Expand Down Expand Up @@ -103,7 +113,9 @@ rolecraft knows where each AI agent looks for skills. When you use a flag like \
const notes = manifest.filter((a) => a.notes)
const notesSection =
notes.length > 0
? `\n## Notes\n\n${notes.map((a) => `- **${a.name}:** ${a.notes}`).join('\n')}\n`
? `\n## Notes\n\n${notes
.map((a) => `- **${a.name}:** ${escapeMarkdown(a.notes)}`)
.join('\n')}\n`
: ''

const mcpFormats = [...new Set(mcpAgents.map((a) => a.mcpSupport.format))]
Expand Down
15 changes: 15 additions & 0 deletions src/agents/manifest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,21 @@ describe('agent manifest', () => {
assert.equal(current, generated)
})

// Agent notes contain literal paths like `~/.zcode/skills/<name>/SKILL.md`.
// VitePress reads a bare `<...>` in a .md file as a Vue tag, and an unclosed
// one aborts the docs build with no link back to the note that caused it.
it('escapes angle brackets in agent notes so the docs build', () => {
const generated = generateAgentsDocs()
const notesSection = generated.slice(generated.indexOf('## Notes'))
for (const line of notesSection.split('\n')) {
assert.ok(
!line.includes('<'),
`unescaped tag in generated notes: ${line}`,
)
}
assert.match(notesSection, /&lt;name&gt;/, 'expected an escaped path')
})

it('matrix token values match the agent manifest', () => {
const manifest = getAgentManifest()
const tokens = getTokenValues()
Expand Down
Loading