Skip to content

Custom presets

presets in .ai-rulez/config.toml lists the tools ai-rulez generates for. Most projects use only built-in presets (claude, cursor, copilot, codex, gemini, …; all 52 are listed in Supported harnesses). A custom preset writes your rules to a file or folder of your choice, for a tool or a document ai-rulez does not ship.

Looking for profiles (named sets of domains)? See Domains and profiles.

.ai-rulez/config.toml
presets = [
"claude",
"cursor",
{ name = "review-bot", type = "markdown", path = "docs/REVIEW_BOT.md", template = """
# {{ .Name }} conventions
{{ range .Rules }}
## {{ .Name }}{{ if .Priority }} ({{ .Priority }}){{ end }}
{{ .Content }}
{{ end }}""" },
{ name = "rules-dir", type = "directory", path = ".mytool/rules" },
{ name = "rules-json", type = "json", path = "build/rules.json" },
]

With two rules, commit-messages (priority: high) and typescript (priority: medium), ai-rulez generate writes the built-in outputs plus:

docs/REVIEW_BOT.md
# acme conventions
## commit-messages (high)
Use Conventional Commits.
## typescript (medium)
No `any`.
.mytool/rules/
├── commit-messages.md
└── typescript.md

build/rules.json:

{
"Context": [],
"Description": "",
"Domains": {},
"Name": "acme",
"Rules": [
{ "Content": "Use Conventional Commits.\n", "Name": "commit-messages", "Priority": "high" },
{ "Content": "No `any`.\n", "Name": "typescript", "Priority": "medium" }
],
"Skills": [],
"Version": "5.0"
}

A custom preset is an inline table in the presets array, mixed freely with built-in names. A config with only custom presets can also use [[presets]] tables.

Key Type Meaning
name string required; identifies the preset in messages; a template can match it against a rule’s Targets
type string markdown, directory or json
path string output file (markdown, json) or folder (directory), relative to the project root
template string optional Go template for markdown and json; see Templates
provider string path to a provider spec instead of type and path; see below

path must stay inside the project; see Output paths.

Type Writes
markdown one file at path. Without a template: a title, the project description, and the rule, context and skill sections.
directory one <id>.md file per rule in the folder path, with a # <id> heading and the priority line. Only rules are written.
json one file at path. Without a template: the template data as indented JSON.
[[presets]]
name = "dev-guide"
type = "markdown"
path = "docs/AI_DEVELOPMENT_GUIDE.md"

markdown and json presets take a template in Go’s text/template syntax. Only the built-in template functions are available (len, printf, eq, index, and, or, not, …) and the actions range, if and with. Any other function fails the run:

Error: generate presets: generate preset review-bot: parse template: template: custom:1: function "now" not defined
Field Contents
.Name project name
.Description project description
.Version config version
.Rules rules of the active profile, root and domains together, in priority order
.Context context files, likewise
.Skills skills, likewise
.Domains map of domain name to { Name, Rules, Context, Skills }

Each rule and context entry has Name and Content, plus Priority and Targets when the frontmatter sets them (Priority is left out with compact = true). A skill entry also has Body (the instructions only), Resources (each with Kind, RelPath, Content, Description) and its other frontmatter keys; its Content includes the inlined reference files.

The same rules apply to every output path a configuration names: a custom preset path, a provider spec’s root.file, outputs.*.dir, sidecars[].path and directories, okf.dir, marketplace.output_dir and codex_skills_dir. validate and generate reject:

  • an empty, absolute or drive- or UNC-prefixed path, and any .. segment;
  • a .git segment anywhere in the path (including the Windows spellings .git. and git~1);
  • a path under .ai-rulez/, .config/ai-rulez/, .hg/ or .svn/.

A preset may write a file that CI or a developer tool runs (.github/workflows/, Makefile, .vscode/tasks.json); the generate summary lists it as exec-file before writing.

Rules and context are ordered by priority (critical, high, medium, low, minimal), then by name. Set priority in a rule’s frontmatter to move it.

Frontmatter targets limits a rule to some outputs of the built-in presets. The markdown, directory and json presets do not apply it: they receive every rule of the active profile. A template can filter on the Targets field itself:

{{ range .Rules }}{{ $bot := false }}{{ range .Targets }}{{ if eq . "review-bot" }}{{ $bot = true }}{{ end }}{{ end }}
{{ if or (not .Targets) $bot }}## {{ .Name }}
{{ .Content }}{{ end }}{{ end }}

Under the default [rules] mode = "split", built-in presets with a rules folder (.claude/rules/, .cursor/rules/, .github/instructions/, …) get one file per rule, and with agents_md = true (the default) the always-on rules go to the shared AGENTS.md. See Rules for each preset in each mode, and AGENTS.md and .agents/skills.

mcp is a utility preset that writes the generic .mcp.json. It runs automatically when MCP servers are configured; you do not need to list it.

Symptom Cause and fix
function "..." not defined The template uses a function that is not a Go built-in. Rewrite it with range/if.
has an unsafe 'path' path leaves the project or points into a control directory; see Output paths.
The output is missing a rule The rule’s domain is not in the active profile, or the template filters it out.
A warning that hooks or permissions are not generated Custom presets have no hook or permission support; both are written for built-in presets only.