Open source · MIT · .NET 10
Your agent knows XAF.
It has never seen your app.
One command changes that.
An agent that has read every page of the DevExpress documentation still does not know that
your Invoice total is calculated from its lines, that
ApproveController refuses to run when the period is closed, or that three
columns were hidden in the Model Editor and appear in no C# file at all.
It will confidently invent all three. That gap is not solvable by better prompting — it is solvable by reading the code.
The difference, in one line
Same code.
Two very different answers.
A real attribute from a real XAF entity. Ask an agent what it does with and without the extraction, and the gap stops being abstract.
[DefaultClassOptions]public class Order : XPCustomObject{ [Association("Customer-Orders")]
Without the extraction
“It filters the customer lookup. Customer probably has an active flag,
so I'll write IsActive = True.”
Confident. Fluent XAF. Wrong — that property does not exist.
With the extraction
“Filters the Customer lookup to unblocked customers.
IsBlocked is a bool on Customer, and this is
XAF criteria syntax — neither SQL nor a C# lambda — evaluated by the database.”
Read from your source: the property, its type, and the entity it belongs to.
[DataSourceCriteria("IsBlocked = False")] public Customer Customer { get; set; } [PersistentAlias("Lines.Sum(LineTotal)")] public decimal Total => /* calculated in the database */}
Where this fits
DevExpress teaches the framework.
This teaches your application.
These compose. Install the official skills for how XAF works, keep the documentation server for the official reference, and add this for the one thing neither of them can know.
Entities and relationships
Properties, types, associations, aggregation, and the XAF attributes that give them
meaning. XPO and EF Core, detected from your using statements.
Controllers and actions
Every action, its target criteria, and the C# that actually runs when someone presses the button.
Rules and the Model Editor
Validation with its messages, conditional appearance, calculated properties — and the
.xafml customizations that exist in no C# file.
The output
An AGENTS.md is read on every request.
So most of it isn't in there.
That file is prepended to every question an agent answers in your repository — its size is a tax paid forever. Seventy kilobytes of entity detail there would crowd out the thing the user actually asked.
So the output is tiered.
The most valuable part is the smallest. The index opens with ground rules — which ORM this application uses and which APIs therefore do not exist in it, that the inventories are complete so anything absent genuinely is, and that some behavior lives in XML rather than in code.
CLAUDE.md and .github/copilot-instructions.md are written too.
Anything you added by hand survives regeneration, and regenerating twice produces identical
bytes.
Live, not a snapshot
Or let the agent
ask questions directly.
A generated file is a snapshot. The MCP server is a connection: seven tools your agent calls against the source while you are still changing it, so it cannot go stale.
What this application is, and the complete list of everything in it.
Every property, relationship, rule and calculation on one entity.
What an action does — including the C# that runs when it fires.
Find a business term, list what the app enforces, read the Model Editor, re-read the source.
Ask for something that isn't there, and the answer is the useful one:
There is no entity called 'PurchaseOrder' in this application.
This is the complete list of 19 entities, extracted from the whole source tree: …
If the user expects 'PurchaseOrder' to exist, it has not been created yet.
A bare “not found” invites an agent to assume it looked in the wrong place and invent the type anyway. Extraction reads the whole tree, which is what makes the stronger claim true.
And for the person who inherits it
Most teams have never seen
their own domain model.
It exists as association attributes scattered across twenty files, and the map of it lives in one person's head — which is exactly the knowledge that leaves when they do.
xaflogic explain writes one self-contained HTML file — no server, no build step,
no request to the network. It opens from an email attachment on a machine with no internet,
which is how handovers actually happen.
Alongside the map: every entity and what each property is, every action with the code it runs, validation with the message the user will actually see, and an index of every criteria expression in the application — a dialect that is neither SQL nor C# and is otherwise collected nowhere.
Optional, for licensees
Tell your code apart
from DevExpress's.
Reading source alone leaves one question unanswerable: is
DeleteObjectsViewController something your team wrote, or something DevExpress
ships? xaflogic catalog build reads your own installation and answers it.
“This extends built-in behavior”
A controller deriving from DeleteObjectsViewController is changing how
deletion works application-wide, not adding a feature beside it.
“This attribute is yours”
An attribute in neither XAF nor .NET was invented by your team — its meaning lives in your codebase and in no documentation anywhere.
Install
Two minutes.
A .NET global tool. No account, no API key, no server.
$ dotnet tool install -g XafLogicExplainer.Cli # Write the context files at your solution root$ xaflogic agents --project "C:\MySolution\MyApp.Module" ✓ AGENTS.md✓ CLAUDE.md✓ .github\copilot-instructions.md+ 7 detail files in .xaflogic/ # Ask your agent something only this codebase could answer.
Prefer the agent to query live? Install the plugin:
/plugin marketplace add peopleworks/XAFLogicExplainer/plugin install xaf-logic-explainer@peopleworks-xaf # Pair it with the official DevExpress skills:/plugin marketplace add DevExpress/agent-skills/plugin install dx-xaf@DevExpress-agent-skills