Skip to main content
AI tutorials

Build Predictable AI-Generated Backends with kybes

This tutorial explains how kybes turns YAML database schemas into consistent C#, Python, TypeScript, and Java models. You will install the Claude Code plugin, configure a project, define tables and queries, use generated repositories, add custom methods safely, and enforce architecture with hooks and CI checks.

Build Predictable AI-Generated Backends with kybes

What kybes does

kybes is a Claude Code plugin for generating predictable backend code from YAML database schemas. It standardizes folders, file names, repository methods, validation, pagination, transactions, indexes, and tests across C#, Python, TypeScript, and Java projects.

Instead of asking an AI agent to remember an architecture document, kybes enforces the architecture through deterministic generation, dedicated agents, folder-specific rules, hooks, and CI checks. The same schema produces byte-identical generated output across projects.

The central rule is simple: the schema is the source of truth, generated files are not edited manually, and custom behavior belongs in the model file associated with its table.

How the generated structure works

For each table, kybes creates two model layers:

  • model/generated/<Table> contains generated entities, CRUD operations, relations, declared queries, cursor pagination, and validation. These files are regenerated and should not be edited.
  • model/<Table> is the safe location for custom methods. C# uses a partial class, while Python, TypeScript, and Java use a subclass-based approach.

A typical project also includes generated JSON Schemas, PostgreSQL DDL, index analysis, an index of model files, and generated verification artifacts.

Install kybes

Install through Claude Code

From Claude Code, add the marketplace and install the plugin:

/plugin marketplace add ivandilelio/kybes
/plugin install kybes@kybes

Inside the target project, ask Claude Code to set up kybes in this project. The kybes:kybes-init skill asks which model languages you need and creates the configuration, path rules, CLAUDE.md instructions, an optional scaffold, and a CI workflow.

Hooks remain inactive in repositories that have not been initialized.

Install from the command line

You can also clone the repository and run the installer:

git clone https://github.com/ivandilelio/kybes
kybes/install.sh --target /path/to/project --scaffold --examples \
  --model-langs csharp,python,typescript,java

The installer is idempotent. After cloning a configured project, teammates only need to run tools/kybes/setup.sh once.

Check the requirements

The hooks and generator require python3 with only the standard library. Generated runtimes require the corresponding language dependencies:

  • C#: net8.0, Entity Framework Core 8, and a provider such as Npgsql.
  • Python: Python 3.9 or newer and SQLAlchemy 2.
  • TypeScript: TypeORM, reflect-metadata, and enabled experimentalDecorators and emitDecoratorMetadata compiler options.
  • Java: Jakarta Persistence 3.1, Hibernate 6.2 or newer, and Jackson for json columns.

Define a database schema

Create a YAML file under schemas/db. The following example defines an order table with a unique order number, a required customer relationship, a declared query, and sortable cursor pagination:

table: Ordini
columns:
  - { name: Id, type: uuid, primary_key: true }
  - { name: Numero, type: string, length: 20, required: true, unique: true }
  - { name: ClienteId, type: uuid, required: true }
  - { name: Data, type: date, required: true }
relations:
  - { name: Cliente, kind: many_to_one, target: Clienti, foreign_key: ClienteId }
queries:
  - name: DelClienteDal
    where: [ClienteId, { column: Data, op: gte, param: DaData }]
    order_by: [{ column: Data, dir: desc }]
pagination:
  default_order: [{ column: Data, dir: desc }]
  sortable: [Data, Numero]

Save the file as schemas/db/Ordini.yaml. A schema change triggers regeneration for the configured languages, updates the model index, and recalculates index recommendations.

Use the generated API

For the example schema, kybes generates equivalent repository capabilities in each language. Naming follows the conventions of the target language:

  • Read by key: GetByIdAsync in C#, get_by_id in Python, and getById in TypeScript or Java.
  • Cursor pagination: ListPageAsync, list_page, or listPage.
  • Unique-column lookup: FindByNumeroAsync, find_by_numero, or findByNumero.
  • Foreign-key lookup: ListByClienteIdAsync, list_by_cliente_id, or listByClienteId.
  • Declared query: ListDelClienteDalAsync, list_del_cliente_dal, or listDelClienteDal.

The generated API also provides validated create, update, and delete operations, relation accessors, and cursor-based pages represented by a request and a page containing items and a next cursor.

Declare queries instead of writing data access in handlers

Put supported query conditions in the schema rather than importing an ORM or database driver into a Lambda, service, or controller. kybes supports operators including eq, ne, lt, lte, gt, gte, in, prefix, and is_null.

The generator creates the repository method and analyzes its access path. In the example, the foreign-key and date conditions lead to an index on (ClienteId, Data). The decision is recorded in db/generated/indexes.md.

Add custom model behavior

When generated methods are not enough, add custom methods to the non-generated model file, such as model/Fornitori.py or the equivalent file for the selected language. Do not edit the generated implementation.

Custom methods must not collide with generated method names. They also require a traced test in tests/custom/ before the work can finish. The expected test identifier format is TC-<Table>-….

Keep data access inside the model layer. A handler should call a generated or custom model method, not create its own SQLAlchemy, Entity Framework, TypeORM, or Hibernate query.

Understand kybes guardrails

kybes hooks run throughout the development workflow. Before a write, they can block ORM or database-driver imports outside the model, edits to generated files, invalid model folders, method collisions, and secrets in clear text.

After a schema write, kybes can regenerate models, run linters, and report architecture issues. Before completion, the main agent and every subagent must pass the architecture check, generator check, verification script, and project test commands.

The default stop-gate checks include:

  • arch_check, including detection of duplicated blocks of eight or more lines.
  • gen --check to confirm generated output is current.
  • verify.py for model tests and coverage thresholds per ASIL.
  • The project's own test commands.

The same checks run in CI with --strict. Rules can be configured as block, warn, or off in .claude/kybes.config.json. The agent is not allowed to modify this configuration file.

Use transactions, pagination, and indexes safely

kybes generates cursor pagination from the schema's default ordering and allowed sortable columns. This produces a keyset-based page request and a page containing items and a next cursor. Cursor formats are shared across the supported languages, which helps different services and clients interoperate.

Transactions use a Unit of Work with per-table isolation levels and automatic retry handling for serialization failures and deadlocks. Declared access paths are analyzed for ideal indexes; missing indexes are created and redundant indexes are flagged. Prefix searches can use PostgreSQL varchar_pattern_ops where appropriate.

Configure multi-tenancy

Multi-tenancy can be configured per table using one of the supported strategies:

  • A tenant column, with every generated method filtered and unique constraints scoped per tenant.
  • PostgreSQL row-level security.
  • A schema per tenant.
  • A database per tenant.

The tenant is bound to the ORM session, and kybes generates isolation tests for the configured strategy.

Review the generated project layout

A configured project follows a predictable structure:

your-project/
├── schemas/db/<Table>.yaml
├── schemas/generated/json/<Table>.schema.json
├── libs/db-models/<language>/…/model/
│   ├── <Table>.{cs,py,ts} | <Table>Repository.java
│   └── generated/
├── libs/db-models/<language>/tests/
│   ├── generated/
│   └── custom/
├── docs/generated/verification/
├── db/generated/ddl/postgres/_all.sql
├── services/<context>/{functions,ms}/
├── jobs/
├── libs/utils/
├── libs/errors/
├── frontend/
├── infra/
├── MODEL_INDEX.md
└── .claude/kybes.config.json

Everything under a generated/ folder belongs to kybes. Other model files, custom tests, schemas, and application code are maintained by your team according to the configured rules.

Verify the result

The repository includes verification for generated code, hooks, SQL, and cross-language behavior. Tests cover CRUD, relations, cascades, unique constraints, pagination edge cases, query operators, and Unit of Work behavior.

Generated unit tests derive requirements and test cases from each schema. The verification workflow includes equivalence classes, boundary values, error guessing, MC/DC for ASIL C and D, traceability, and coverage gates per table. The repository also checks that generated PostgreSQL DDL parses correctly and that cursors produced by one supported language can be accepted by the others.

For safety-critical work, kybes automates parts of ISO 26262-6 at software-unit level, but it does not replace a complete safety plan, hazard analysis, tool qualification, independent review, or organizational certification process.

Conclusion

kybes provides a schema-first workflow for predictable AI-generated backends. Define tables, relations, queries, pagination, and tenancy rules once; let the deterministic generator create the language-specific models, indexes, DDL, validation, and tests; then place custom behavior in the approved model layer.

With Claude Code agents, write-time hooks, duplicate-code detection, generated verification, and strict CI checks, the project remains consistent even as the codebase and AI context grow. For deeper reference material, explore the project's documentation and source repository.