--- title: 'How to Customize BMad' description: Customize agents and workflows while preserving update compatibility sidebar: order: 8 --- Tailor agent personas, inject domain context, add capabilities, and configure workflow behavior -- all without modifying installed files. Your customizations survive every update. ## When to Use This - You want to change an agent's personality or communication style - You need to give an agent persistent facts to recall (e.g. "our org is AWS-only") - You want to add procedural startup steps the agent must run every session - You want to add custom menu items that trigger your own skills or prompts - Your team needs shared customizations committed to git, with personal preferences layered on top :::note[Prerequisites] - BMad installed in your project (see [How to Install BMad](./install-bmad.md)) - Python 3.11+ on your PATH (for the resolver script -- uses stdlib `tomllib`, no `pip install`, no `uv`, no virtualenv) - A text editor for TOML files ::: ## How It Works Every customizable skill ships a `customize.toml` file with its defaults. This file defines the skill's complete customization surface -- read it to see what's customizable. You never edit this file. Instead, you create sparse override files containing only the fields you want to change. ### Three-Layer Override Model ```text Priority 1 (wins): _bmad/custom/{skill-name}.user.toml (personal, gitignored) Priority 2: _bmad/custom/{skill-name}.toml (team/org, committed) Priority 3 (last): skill's own customize.toml (defaults) ``` The `_bmad/custom/` folder starts empty. Files only appear when someone actively customizes. ### Merge Rules (by shape, not by field name) The resolver applies four structural rules. Field names are never special-cased — behavior is determined purely by the value's shape: | Shape | Rule | |---|---| | Scalar (string, int, bool, float) | Override wins | | Table | Deep merge (recursively apply these rules) | | Array of tables where every item has a `code` or `id` field | Merge by that key — matching keys **replace in place**, new keys **append** | | Any other array (scalars, mixed, tables without `code`/`id`) | **Append** — base items first, then team items, then user items | **No removal mechanism.** Overrides cannot delete base items. If you need to suppress a default menu item, override it by `code` with a no-op description or prompt. If you need to restructure an array more deeply, fork the skill. #### The `code` / `id` convention BMad uses `code` (short identifier like `"BP"` or `"R1"`) and `id` (longer stable identifier) as merge keys on arrays of tables. If you author a custom array-of-tables that should be replaceable-by-key rather than append-only, give every item a `code` or `id` field. ### Some agent fields are read-only `agent.name` and `agent.title` live in `customize.toml` as source-of-truth metadata, but the agent's SKILL.md doesn't read them at runtime — they're hardcoded identity. Putting `name = "Bob"` in an override file has no effect. If you genuinely need a different-named agent, copy the skill folder, rename it, and ship it as a custom skill. ## Steps ### 1. Find the Skill's Customization Surface Look at the skill's `customize.toml` in its installed directory. For example, the PM agent: ```text .claude/skills/bmad-agent-pm/customize.toml ``` (Path varies by IDE -- Cursor uses `.cursor/skills/`, Cline uses `.cline/skills/`, and so on.) This file is the canonical schema. Every field you see is customizable (excluding the read-only identity fields noted above). ### 2. Create Your Override File Create the `_bmad/custom/` directory in your project root if it doesn't exist. Then create a file named after the skill: ```text _bmad/custom/ bmad-agent-pm.toml # team overrides (committed to git) bmad-agent-pm.user.toml # personal preferences (gitignored) ``` :::caution[Do NOT copy the whole `customize.toml`] Override files are **sparse**. Include only the fields you're changing — nothing else. Every field you omit is inherited automatically from the layer below (team from defaults, user from team-or-defaults). Copying the full `customize.toml` into an override is actively harmful: the next update ships new defaults, but your override file locks in the old values. You'll silently drift out of sync with every release. ::: **Example — changing the icon and adding one principle**: ```toml # _bmad/custom/bmad-agent-pm.toml # Just the fields I'm changing. Everything else inherits. [agent] icon = "🏥" principles = [ "Ship nothing that can't pass an FDA audit.", ] ``` This appends the new principle to the defaults (leaving the shipped principles intact) and replaces the icon. Every other field stays as shipped. ### 3. Customize What You Need All examples below assume BMad's flat agent schema. Fields live directly under `[agent]` — no nested `metadata` or `persona` sub-tables. #### Scalars (icon, role, identity, communication_style) Scalar overrides simply win. You only need to set the fields you're changing: ```toml # _bmad/custom/bmad-agent-pm.toml [agent] icon = "🏥" role = "Drives product discovery for a regulated healthcare domain." communication_style = "Precise, regulatory-aware, asks compliance-shaped questions early." ``` #### Persistent Facts, Principles, Activation Hooks (append arrays) All four arrays below are append-only. Team items run after defaults, user items run last. ```toml [agent] # Static facts the agent keeps in mind the whole session — org rules, domain # constants, user preferences. Distinct from the runtime memory sidecar. # # Each entry is either a literal sentence, or a `file:` reference whose # contents are loaded as facts (glob patterns supported). persistent_facts = [ "Our org is AWS-only -- do not propose GCP or Azure.", "All PRDs require legal sign-off before engineering kickoff.", "Target users are clinicians, not patients -- frame examples accordingly.", "file:{project-root}/docs/compliance/hipaa-overview.md", "file:{project-root}/_bmad/custom/company-glossary.md", ] # Adds to the agent's value system principles = [ "Ship nothing that can't pass an FDA audit.", "User value first, compliance always.", ] # Runs BEFORE the standard activation (persona, persistent_facts, config, greet). # Use for pre-flight loads, compliance checks, anything that needs to be in # context before the agent introduces itself. activation_steps_prepend = [ "Scan {project-root}/docs/compliance/ and load any HIPAA-related documents as context.", ] # Runs AFTER greet, BEFORE the menu. Use for context-heavy setup that should # happen once the user has been acknowledged. activation_steps_append = [ "Read {project-root}/_bmad/custom/company-glossary.md if it exists.", ] ``` **Why two hooks?** Prepend runs before greeting so the agent can load context it needs to personalize the greeting itself. Append runs after greeting so the user isn't staring at a blank terminal while heavy scans complete. #### Menu Customization (merge by `code`) The menu is an array of tables. Each item has a `code` field (BMad convention), so the resolver merges by code: matching codes replace in place, new codes append. TOML array-of-tables syntax uses `[[agent.menu]]` for each item: ```toml # Replace the existing CE item with a custom skill [[agent.menu]] code = "CE" description = "Create Epics using our delivery framework" skill = "custom-create-epics" # Add a new item (code RC doesn't exist in defaults) [[agent.menu]] code = "RC" description = "Run compliance pre-check" prompt = """ Read {project-root}/_bmad/custom/compliance-checklist.md and scan all documents in {planning_artifacts} against it. Report any gaps and cite the relevant regulatory section. """ ``` Each menu item has exactly one of `skill` (invokes a registered skill) or `prompt` (executes the text directly). Items not listed in your override keep their defaults. #### Referencing Files When a field's text needs to point at a file (in `persistent_facts`, `activation_steps_prepend`/`activation_steps_append`, or a menu item's `prompt`), use a full path rooted at `{project-root}`. Even if the file sits next to your override in `_bmad/custom/`, spell out the full path: `{project-root}/_bmad/custom/info.md`. The agent resolves `{project-root}` at runtime. ### 4. Personal vs Team **Team file** (`bmad-agent-pm.toml`): Committed to git. Shared across the org. Use for compliance rules, company persona, custom capabilities. **Personal file** (`bmad-agent-pm.user.toml`): Gitignored automatically. Use for tone adjustments, personal workflow preferences, and private facts the agent should keep in mind. ```toml # _bmad/custom/bmad-agent-pm.user.toml [agent] persistent_facts = [ "Always include a rough complexity estimate (low/medium/high) when presenting options.", ] ``` ## How Resolution Works On activation, the agent's SKILL.md runs a shared Python script that does the three-layer merge and returns the resolved block as JSON. The script uses the Python standard library's `tomllib` module (no external dependencies), so plain `python3` is enough: ```bash python3 {project-root}/_bmad/scripts/resolve_customization.py \ --skill {skill-root} \ --key agent ``` **Requirements**: Python 3.11+ (earlier versions don't include `tomllib`). No `pip install`, no `uv`, no virtualenv. macOS 13+, Ubuntu 22.04+, Debian 12+, and Fedora 37+ all ship 3.11 or newer. `--skill` points at the skill's installed directory (where `customize.toml` lives). The skill name is derived from the directory's basename, and the script looks up `_bmad/custom/{skill-name}.toml` and `{skill-name}.user.toml` automatically. Useful invocations: ```bash # Resolve the full agent block python3 {project-root}/_bmad/scripts/resolve_customization.py \ --skill /abs/path/to/bmad-agent-pm \ --key agent # Resolve a single field python3 {project-root}/_bmad/scripts/resolve_customization.py \ --skill /abs/path/to/bmad-agent-pm \ --key agent.icon # Full dump python3 {project-root}/_bmad/scripts/resolve_customization.py \ --skill /abs/path/to/bmad-agent-pm ``` Output is always JSON. If the script is unavailable on a given platform, the SKILL.md tells the agent to read the three TOML files directly and apply the same merge rules. ## Workflow Customization Workflows (skills that drive multi-step processes like `bmad-product-brief`) share the same override mechanism as agents. Their customizable surface lives under `[workflow]` instead of `[agent]`, keeping the two namespaces cleanly separated: ```toml # _bmad/custom/bmad-product-brief.toml [workflow] # Same prepend/append semantics as agents — runs before and after the workflow's # own activation steps. Overrides append to defaults. activation_steps_prepend = [ "Load {project-root}/docs/product/north-star-principles.md as context.", ] activation_steps_append = [] # Same literal-or-file: semantics as the agent variant. Loaded as foundational # context for the duration of the workflow run. persistent_facts = [ "All briefs must include an explicit regulatory-risk section.", "file:{project-root}/docs/compliance/product-brief-checklist.md", ] # Scalar: runs once the workflow finishes its main output. Override wins. on_complete = "Summarize the brief in three bullets and offer to email it via the gws-gmail-send skill." ``` The same field conventions cross the agent/workflow boundary: `activation_steps_prepend`/`activation_steps_append`, `persistent_facts` (with `file:` refs), menu-style `[[…]]` tables with `code`/`id` for keyed merge. The resolver applies the same four structural rules regardless of the top-level key. SKILL.md references follow the namespace: `{workflow.activation_steps_prepend}`, `{workflow.persistent_facts}`, `{workflow.on_complete}`. Any additional fields a workflow exposes (output paths, toggles, review settings, stage flags) follow the same merge rules based on their shape. Read the workflow's `customize.toml` to see what it makes customizable. ## Troubleshooting **Customization not appearing?** - Verify your file is in `_bmad/custom/` with the correct skill name - Check TOML syntax: strings must be quoted, table headers use `[section]`, array-of-tables use `[[section]]`, and any scalar or array keys for a table must appear *before* any of that table's `[[subtables]]` in the file - For agents, customization lives under `[agent]` -- fields written below that header belong to `agent` until another table header begins - Remember `agent.name` and `agent.title` are read-only; overrides there have no effect **Updates broke my customization?** - Did you copy the full `customize.toml` into your override file? **Don't.** Override files should contain only the fields you're changing. A full copy locks in old defaults and silently drifts every release. Trim your override back to just the deltas. **Need to see what's customizable?** - Read the skill's `customize.toml` -- every field there is customizable (except `name` and `title`) **Need to reset?** - Delete your override file from `_bmad/custom/` -- the skill falls back to its built-in defaults