Practice Profiles

Grimoire maintains skills and standards. Profiles are yours to own and share.

A profile is a named, curated set of skills. Set profiles = ["oop"] under [standards] in grimoire.toml and grimoire resolves it — no list to maintain unless you want one.


How It Works

# grimoire.toml
[standards]
profiles = ["oop"]

Each profile name resolves using depth-anywhere glob matching, not a fixed path:

  1. Project first — checked against .grimoire/ in your project root. A name like "engineering" matches .grimoire/engineering.toml or any .toml file nested under a .grimoire/**/engineering/ directory, at any depth.
  2. Then every installed package, in priority order (highest first — see Config), same depth-anywhere matching against each package’s tree.
  3. Qualified refs<package>/<name> (e.g. acmecorp/engineering) or a full package URL (owner/repo@version:path) scope the search to that one package instead of walking all of them.
  4. No file match anywhere — grimoire falls back to matching skills by tag (tags in a skill’s frontmatter containing <name>), then by domain path (<name> matching a domain/subdomain directory), when the caller has package context to search.

A bare name with no file anywhere still works via the tag/domain fallback — profiles = ["oop"] is usable immediately without creating any file, as long as skills are tagged oop.


Multiple Profiles

Combine paradigms by listing multiple profiles:

[standards]
profiles = ["clean-architecture", "tdd"]  # clean-architecture wins conflicts

Array order = conflict priority. When two profiles include skills with conflicting guidance, the first profile in the array wins.

Duplicate skills (same skill name resolved by two profiles) are deduplicated — activated once, keeping the first-listed profile’s priority.


Profile File Schema

Create a file to curate exactly which skills activate — useful when the tag set is too broad, or you want a team-specific subset. Subdirectories are supported; nest profile files however you like under .grimoire/.

# .grimoire/my-team.toml
name = "my-team"
description = "Our backend team's default practices"
tags = ["backend"]                # optional: also bulk-activate anything tagged "backend"
extends = ["clean-architecture"]  # optional: inherit another profile's resolved skills first

[[skills]]
name = "apply-solid-principles"
priority = 10                     # optional, default 50 — lower runs/ranks first

[[skills]]
name = "apply-domain-driven-design"

exclude = ["apply-kiss-principle"]  # optional: remove a skill even if extends/tags included it

compliance-threshold = 80           # optional: BPDD threshold this profile recommends
compliance-threshold-error = 0

Fields

FieldTypeRequiredDescription
namestringnoProfile identifier — defaults to the filename if omitted
descriptionstringnoOne sentence, when to use this profile
extendsstring[]noOther profile names to inherit skills from first (recursive, cycle-safe)
tagsstring[]noBulk-activate every skill whose frontmatter tags includes any of these, falling back to a domain-path match if no tagged skill is found
skills[].namestringyes (per entry)Skill name (matches frontmatter name:)
skills[].prioritynumbernoLower number = higher priority; unset defaults to 50
excludestring[]noSkill names removed from the final resolved list, even if extends/tags/skills included them
compliance-threshold / compliance-threshold-errornumbernoBPDD thresholds this profile recommends

Resolution order inside one profile: extends (inherited skills first) → tags (bulk additions) → explicit [[skills]] (can override priority of an already-included skill) → exclude (final removal pass). After all listed profiles resolve this way, [standards.<domain>].practices and .disabled from your settings are applied on top — practices re-prioritizes or adds matching skills, disabled removes them unconditionally.


Inline Profiles

A profile can also be embedded directly in grimoire.toml instead of its own file — same fields as above:

# grimoire.toml
[profiles.my-team]
description = "Our backend team's default practices"

[[profiles.my-team.skills]]
name = "apply-solid-principles"

[[profiles.my-team.skills]]
name = "apply-domain-driven-design"

Grimoire checks for a file-based profile first; if none exists, it falls back to a matching [profiles.<name>] block.


The Ecosystem

Grimoire ships no built-in profiles — the tag system covers the common cases. But you can:

  • Share your team profile — commit .grimoire/ to your repo
  • Publish a community profile — ship it as an installable package (see Config) so others can extends or reference it with a qualified <package>/<name> ref

This mirrors how eslint-config-airbnb or VS Code profiles work: the tool ships primitives, the community ships bundles.


Profiles vs Practices

Two complementary keys, both under [standards] in grimoire.toml:

profilespractices
Where[standards] top-levelInside a [standards.<domain>] section
ScopeGlobal — activates skills across all domainsScoped — applies to one domain only
GranularityBulk — a full resolved profile’s worth of skillsExplicit ordered list of specific skills
Use whenDeclaring paradigm intent for the projectFine-tuning skill priority for a specific domain
# grimoire.toml
[standards]
profiles = ["oop"]              # load all oop-tagged skills globally

[standards.engineering.architecture]
practices = [                   # override: in architecture, prefer these specific skills in this order
  "apply-solid-principles",
  "apply-law-of-demeter"
]

profiles sets the baseline. practices overrides per domain.

Can I use practices = ["OOP"] instead of profiles?

Yes — it works as a loose hint. The AI will lean toward OOP conventions based on its training. But it’s less precise than profiles = ["oop"]:

  • No guaranteed skill steps — depends on the AI’s interpretation of “OOP”
  • No dedup or conflict logic between skills
  • Not scoped to specific installed SKILL.md files

For best results, use both:

[standards]
profiles = ["oop"]                          # activate oop skill bundle (specific skills)

[standards.engineering.architecture]
practices = ["OOP"]                         # also pin as explicit preference for this domain

Examples

What you writeWhat happens
profiles = ["oop"]Checked as a file first (project, then packages); falls back to a tag query for oop
profiles = ["functional"]Same — file lookup first, then tag query
profiles = ["clean-architecture", "tdd"]Both resolved and merged; clean-architecture wins conflicts
profiles = ["my-team"]Matches .grimoire/my-team.toml (or nested under a my-team/ dir) — activates its fully resolved skill list
profiles = ["acmecorp/engineering"]Qualified ref — resolves only within the acmecorp package