AI Integration

AI Workflow

How AI agents and the compiler work together to enrich your types.
Experimental

AI-generated human-readable labels & errors

Field labels and error messages for your forms and UI, kept in sync with your type.

AI-generated real-world mock data

Believable sample data (real names, emails, addresses) for your tests and demos, every value valid for its field.

How Enrichment Works

The compiler can't invent a field label, an error message or a sample name, so your agent fills those in.

1The compiler scaffolds

From your type it writes a source file, every field in place, correctly typed, each blank marked.

2The AI agent fills the gaps

The agent fills the blanks with labels, messages and sample values, guided by the type.

3The compiler checks & keeps in sync

It checks every value against the type and updates the file as your type changes, keeping your edits.

FriendlyText

import type * as TF from '@mionjs/run-types/formats';

// models/user.ts
export interface User {
  name: TF.String<{ minLength: 2; maxLength: 60 }>;
  age: TF.Number<{ min: 0; max: 120 }>;
  email: TF.Email;
}
import type { FriendlyText } from '@mionjs/run-types';
import type { User } from './user';

// @todo: generated skeleton — fill in real data, then delete this line
export const friendlyUser: FriendlyText<User> = {
  rt$label: '',
  rt$errors: { type: '' },
  name: {
    rt$label: '',
    rt$errors: {
      type: '',
      minLength: { one: '', other: '' },
      maxLength: { one: '', other: '' },
    },
  },
  age: {
    rt$label: '',
    rt$errors: {
      type: '',
      min: { one: '', other: '' },
      max: { one: '', other: '' },
    },
  },
  email: {
    rt$label: '',
    rt$errors: {
      type: '',
      minLength: { one: '', other: '' },
      maxLength: { one: '', other: '' },
      pattern: '',
    },
  },
};
import type { FriendlyText } from '@mionjs/run-types';
import type { User } from './user';

export const friendlyUser: FriendlyText<User> = {
  rt$label: 'User account',
  rt$errors: { type: '' },
  name: {
    rt$label: 'Full name',
    rt$errors: {
      type: '$[label] must be a valid name',
      minLength: '$[label] needs at least $[val] characters',
      maxLength: '$[label] allows at most $[val] characters',
    },
  },
  age: {
    rt$label: 'Age',
    rt$errors: {
      type: '$[label] must be a number',
      min: '$[label] must be at least $[val]',
      max: '$[label] must be no more than $[val]',
    },
  },
  email: {
    rt$label: 'Email',
    rt$errors: { type: '', minLength: '', maxLength: '', pattern: 'Enter a valid email address' },
  },
};

MockData

import type * as TF from '@mionjs/run-types/formats';

// models/user.ts
export interface User {
  name: TF.String<{ minLength: 2; maxLength: 60 }>;
  age: TF.Number<{ min: 0; max: 120 }>;
  email: TF.Email;
}
import type { MockData } from '@mionjs/run-types';
import type { User } from './user';

// @todo: generated skeleton — fill in real data, then delete this line
export const mockUser: MockData<User> = {
  name: { pool: [] },
  age: { pool: [] },
  email: { pool: [] },
};
import type { MockData } from '@mionjs/run-types';
import type { User } from './user';

export const mockUser: MockData<User> = {
  name: { pool: ['Alice Martin', 'Liang Wei', 'Fatima Noor', /* …50+ */] },
  age: { pool: [], min: 18, max: 95 },
  email: { pool: ['[email protected]', '[email protected]', /* … */] },
};

Agent Skills for Enrichment

Ready-made agent skills teach an AI agent the enrichment workflow, and the agent picks the right one on its own. The main skill covers the commands and the JSDoc tags they use (@rtType, @rtIds, @rtOrphan, @rtOrphanChild, @todo); two more cover writing labels and error messages, and mock data.

npx mion-skills --claude

--claude writes into .claude/skills/, --agent into .agent/skills/, --dir <path> into another folder.

Generated Enrichment Files

enrich writes an ordinary TypeScript file that you commit and can safely edit. A new field gets a new blank, a changed field is flagged as stale, a removed field is kept as a comment until --prune.

The files live under <genDir>/enriched (see genDir), by default src/.mion/enriched: friendly maps under friendly/, mock data under mock/, translations under i18n/<locale>/. Each file follows your source file's path from the tsconfig folder, or from rootDir when set. For src/models/user.ts:

src/.mion/enriched/friendly/src/models/user.ts
src/.mion/enriched/mock/src/models/user.ts

Enrichment Commands

A small CLI drives the loop, for your agent or your CI. An opt-in bundler plugin option runs the same scaffold and sync in your dev server (see Configuration).

CommandWhat it does
enrich <file> <Type>Scaffold the source file with the blanks the agent fills.
enrich … --updateRe-sync the file after a type change, keeping your filled-in values.
enrich … --pruneClean up entries left behind by deleted types or fields.
enrich [files] --no-emitCheck, writing nothing. Fails on wrong or stale content, allows unfilled blanks. Good before a commit.
enrich [files] --require-completeEverything --no-emit catches, plus anything unfinished: an unfilled @todo, a blank value, a missing or out of date translation. With the bundler plugin option on, a production build runs this check too. Good for CI and releases.
enrich --i18n <locale>Scaffold the translation files for a locale, or all for every configured one. Takes --update and --prune like plain enrich.
enrich --i18n <locale> --no-emitReport a locale's translation status (or all), writing nothing. Add --require-complete (or set i18n.strict) to fail CI on anything untranslated or out of date.

Both checks list what is missing and take --json for scripts. The lint rules report the same errors in your editor. Set mion/warning to error to block unfinished files at commit time.

Every command takes --tsconfig <path>. Without it, the CLI searches upward from the current directory, like tsc. A config that fails to load stops the command with an error.

Any agent that can run shell commands (Claude Code, Cursor, your own) can drive them.

Shipped today: the FriendlyText<T> / MockData<T> types (checked against your type by TypeScript), the createFriendlyText and createFriendlyTextI18n renderers, the createMockDataFn({ data }) integration, and the CLI commands above. The always-on build diagnostics described here are in active development.

Next: human-readable labels & errors, real-world mock data, and translations for the friendly text.

Copyright © 2026