When an AI agent starts working on a DarJS app, it faces a structural blindness problem.
The models are defined in files. The fields are declared statically. But the actual shape of a model at runtime — after six mixins have composed their fields into it, after transitions have been defined, after the manifest has wired everything together — that shape doesn’t exist anywhere a static reader can find in one place.
To know what fields Order has, you’d have to read Order.js, then find each mixin call, then read each mixin to see what fields it contributes. For a model with four mixins, that’s five files. For seven models, that’s potentially thirty-five reads before you’ve done any actual work.
This is the introspection gap: the runtime shape of your app is not directly queryable.
The wrong solution: read more files
The first instinct is to just give the AI more context — load all the model files upfront, read the manifest, let it reason about composition. This works at small scale. At medium scale it’s expensive. At large scale it breaks: you’ve spent your context budget on setup before the actual task begins.
The deeper problem is that this approach doesn’t compose. Every new capability you add to your framework — a new mixin pattern, a new field type, a new config key — makes the static reading more complex. The AI’s ability to understand the app degrades as the framework evolves, because it’s reading implementation details instead of a stable interface.
The right solution: a live introspection endpoint
dar inspect is a CLI command that answers questions about your app’s runtime shape:
dar inspect models → all models, field counts, mixin names, transitions
dar inspect model Order → full field table with types, enums, relations
dar inspect pages → all PageDefs with columns, actions, widgets
dar inspect page order → full PageDef detail including relations and wizard
Every subcommand accepts --json for machine-readable output. That means an AI agent can run dar inspect model Order --json and get a complete, structured description of Order — fields from every mixin included, transitions listed, status field identified — in one call, without reading a single source file.
The implementation is not complex. dar inspect calls require() on the manifest, invokes ModelClass.collectFields() on each model, walks the prototype chain for mixin markers, and formats the result. It’s 240 lines of straightforward Node. The insight is not the code — it’s the decision to build it at all.
What this changes for an AI agent
Without dar inspect, an agent working on a DarJS app has to triangulate. “Does Order have a total_ttc field?” requires reading Order.js, finding Model.with(Orderable, Billable), reading both mixins, checking their field definitions. Four reads to answer one binary question.
With dar inspect, the answer is dar inspect model Order --json | grep total_ttc. One call. Zero source reads.
This changes the economics of working on the codebase. Questions that previously cost 4-8 file reads now cost one CLI call. The agent can ask more questions, explore more confidently, and spend its context budget on actual decisions instead of structural archaeology.
The MCP connection
dar inspect was designed with a specific downstream use in mind: an MCP server that exposes the same queries as tools.
An MCP-wrapped inspect_model(name) would let any AI — not just one running in a terminal — query the live shape of a DarJS app during a conversation. The AI asks “what fields does Order have?”, the MCP server calls dar inspect model Order --json, and the answer comes back structured, current, and complete.
This is the pattern: CLI first, then MCP wrapper. The CLI is useful immediately and verifiable by humans. The MCP wrapper extends the same interface to AI tools that can’t run shell commands. One implementation, two audiences.
The general principle
Every framework that expects AI agents to work on the apps it powers should ask: what does an agent need to know about my app’s runtime shape, and can I expose that as a queryable endpoint?
It’s not enough to have good documentation. Documentation describes the framework. An introspection endpoint describes this app — its models, its fields, its pages, its current configuration. Those are different questions with different answers for every codebase.
The introspection gap is a design gap. Closing it is cheap. The cost of not closing it is paid in file reads, every session, indefinitely.
Next: The MCP server wrapper — same queries, different interface, every AI tool in your stack.