Read this when touching persona definition parsing or frontmatter editing. # Persona file frontmatter ## Purpose Persona definitions are Markdown files in `~/.pi/agent/agents/` with an optional `---` frontmatter block. The extension parses them with a hand-written YAML *subset* parser (no YAML dependency) and edits fields in place so user formatting/comments survive. ## Data model `AgentDef` (parsed): `name`, `description`, `model` (`provider/id`), `thinking` (ThinkingLevel), `tools: string[]`, `excludeTools: string[]`, `prompt` (path to external Markdown file, max 64 KB), body text. | Constant | Value / location | Meaning | |---|---|---| | `AGENTS_SUBDIR` | `agents` | subdir under `~/.pi/agent/` | | `STATE_FILENAME` | `agent-state.json` | persisted active persona name | | `MAX_PROMPT_FILE_BYTES` | 64 * 1024 | hard cap for external prompt files | | `UNSUPPORTED_YAML_SCALAR_PREFIX` | `/^[!&*[{\|>-]/` | scalar prefixes that make the file "unsupported" (read-only in menus) | | `DEFAULT_EFFORT` | `medium` | thinking level when unspecified | ## Business rules - Only a YAML subset is supported: flat `key: value` scalars and block lists (`- item` with 2-space indent, see `DESCRIPTION_BLOCK_INDENT` / `isBlockValueLine`). Anything containing an unsupported scalar prefix (`!`, `&`, `*`, `[`, `{`, `|`, `>`, `-` inline) marks the file as unsupported → shown but not editable. - Files may start with a UTF-8 BOM (`UTF8_BOM` constant) — must be stripped before parsing. - Frontmatter is optional; a file with body only is a valid persona (prompt only). - Field edits (`updateFrontmatterFields`) rewrite ONLY the target key's extent (`findKeyExtent`), leaving all other lines byte-identical — comments and blank lines inside frontmatter must survive. - Model IDs use exactly one `/` separator (`MODEL_ID_SEPARATOR`); thinking values validated against `THINKING_LEVELS`. - Tool entries may be glob-ish patterns (`ssh-manager_*`); they are expanded against tools registered in the running session (`expandToolPatterns`), not matched against a static list. - State file (`agent-state.json`) stores only the active persona **name**; if the named file no longer exists, the state is treated as absent (no error). ## Cross-links - Module map: @specs/module-index.md