Just enough structure to write project skills Your AI agent will discover on its own.
In Bricklayer, a skill is a markdown file the agent loads on demand with development-context category=<name>. The bundled ones cover Magento: plugins, EAV, checkout, Hyvä… Local skills cover Your project, and according to the Bricklayer wiki, they are the main reason to use .bricklayer/ at all.
One directory per concern:
.bricklayer/skills/
├── erp-integration/
│ └── SKILL.md
├── company-conventions/
│ └── SKILL.md
└── vendor-theme-stack/
└── SKILL.md
A directory with no bundled counterpart becomes a new callable category. It shows up in three places: development-context category=erp-integration, the CLAUDE.md categories table under a Project-specific group, and search-docs results marked [Project] and source: local.
That last one is what this post is about. A skill nobody finds is a skill nobody loads.
Making it findable
Name
The directory name is the category the agent types. Short, kebab-case: erp-integration, not Our ERP Integration.
Frontmatter
Optional, stripped before the agent sees the content. Only two keys are read, anything else (like type:) is silently ignored:
---
name: ERP integration
description: Two-module stack — Vendor_ErpSync pulls order status from the ERP via cron; Acme_ErpStock adds a local stock pull reusing the vendor client. Default-scope only. Load before touching either module.
---
| Key | Used for | If missing |
|---|---|---|
name |
display name in search-docs |
title-cased directory name (Erp Integration) |
description |
row in the CLAUDE.md categories table, and search keywords for search-docs and development-context category=list |
falls back to the display name |
Description
This is the part people get wrong. The words in description become the search keywords. The agent working on “order status sync” searches for exactly those words, before it knows Your category exists.
- bad:
description: ERP stuff - good: name the modules, the external system, the data that flows, the scope, and when to load it
And keep it on one line. Only the first line after description: is parsed, a wrapped description silently loses everything after the line break.
Body
Write it like a briefing for a new developer:
# ERP integration
## Modules
- `Vendor_ErpSync` (vendor) - cron job pulls order status
- `Acme_ErpStock` (app/code) - local stock pull, reuses vendor client
## Data flow
ERP -> cron -> queue -> order status update
## Before touching it
- `check-class` on the vendor client before adding plugins
- `message-queue-inspect topic="acme.erp.stock"`
## Rules
- Never call the ERP synchronously from frontend requests
Which modules, where they live, how data flows, what to check first. Point to Bricklayer tools by name, the agent will call them.
Overrides and regenerating
A local directory with the same name as a bundled skill replaces it. .bricklayer/skills/plugin/SKILL.md is served wherever development-context category=plugin would load the bundled one, and the response is tagged [Project] so the agent knows it is Your version.
Use it when Your house rules really differ, e.g. a mandatory plugin naming scheme or sortOrder ranges per vendor. Do not copy a bundled skill just to have it locally, unmodified copies are maintenance burden and miss upstream improvements.
After adding or changing a skill:
vendor/bin/bricklayer update
✓ Regenerated CLAUDE.md
Applied local overrides:
- .bricklayer/skills/erp-integration/SKILL.md
Indexed 1 local file(s) into docs index
Then test discoverability the way the agent would: search-docs query="order status sync". If Your skill is not in the results, the description needs better words.
- One concern per skill. A skill about “everything custom” matches every search and helps with none
- Link skills from
project-context.mdby category name, so the agent sees them even without searching
Start coding!
Source: Project-Local Overrides wiki