# Voxgig SDK customization

> The reason teams fork generators is that customizing feels impossible. Voxgig makes customization the architecture: templates and generator components are copied into your repo, project decisions are declared in the model so regeneration is always safe, and the extension points accept your own components, your own features, and entire custom language targets. A doctor command reports any drift from what a resync would write, so CI can hold the line.

How-to documentation: https://github.com/voxgig/sdkgen/blob/main/docs/how-to/customize-and-propagate-templates.md

## The six levers, from mild to wild

In order of preference: many projects never need more than the first two, and the last three are how the generator itself is built.

### Model

Everything the project decides about itself is declared in `.sdk/model/`, written in [aontu](https://aontu.dev), a JSON-based specification language that is easy to edit by hand and designed for building ontologies. Files unify rather than override, so a contradiction is an error, never a silent win. The API's entities and operations land here from the OpenAPI spec; project decisions (package names, release versions, module paths, active features) go in `project.aon`, which the toolchain creates once and never overwrites. Every declaration is re-read on every generation, so nothing declared here can be lost to a regeneration or an upgrade.

### Templates

The literal source of each SDK that is the same for every API: the transport, the base classes, each feature's implementation. They sit under `.sdk/tm/`, one tree per target, and generation copies them into the SDK with placeholder substitution (`ProjectName` becomes the project's name). Editing one takes effect on the next generate. `doctor` reports every edited template before a resync would revert it, and a durable edit moves into the project's own package, or goes upstream.

### Components

TypeScript generators in `.sdk/src/cmp/` that write the API-shaped source by walking the model: entity classes, test suites, READMEs. The dividing question between the layers: same for every API means template, depends on the API means component. An added component runs on every generation and `doctor` reports it as additive; a forked stock component is reported too, because the next resync would revert it.

### Features

A cross-cutting behaviour (retry, caching, cost tracking) generated into every SDK that activates it. A custom feature is a model file plus its implementation per language, a single file or a whole directory at that target's layout, on the same pipeline hooks and transport wrappers the eighteen shipped features use. Behaviour cases are language-neutral data in `.sdk/test/feature/`, and every generated SDK runs them against its own implementation.

### Targets

An output product generated from the model: an SDK in some language, a CLI, an MCP server. The generator has no hardcoded list, so an added target behaves exactly like a shipped one: `target add` installs it, `generate` emits it, `doctor` watches it. Adding one takes a model file (file extension, comment syntax, module name), a template tree, and components for the API-shaped parts; generation phases (readme, agent guide, tests) can be switched per target.

### Packages

The mechanism for EXTERNAL targets and features. An sdkgen package is any folder with a `sdkgen-package.json` manifest beside a `.sdk/` tree: a directory in the repo, a checkout, or an npm module. `package add` installs everything it provides and records provenance, which is what a resync reads: stock content refreshes from sdkgen, project content from the project's own package, and neither clobbers the other. `package check` validates a package for authoring. The bundled languages arrive the same way.

## The worked example

https://github.com/voxgig-sdk/voxgig-elementdemo-sdk generates a periodic-table SDK in TypeScript, Go, Python and Java, then customizes everything above from inside its own repo:

- An entirely custom Bash target: curl for transport, jq for data, one generated function per entity operation, an offline test mode, and a thin CLI.
- A custom elementcard feature that renders element-shaped results as ASCII periodic-table tiles, implemented in all five targets.
- Language-neutral corpus cases in the project's own test data assert the exact card string, byte for byte, in every language.
- Both come from the repo's own sdkgen package (`ext/`), installed with `voxgig-sdkgen package add ../ext`.

## The safety mechanism

Generation itself diff-merges by default: when a generated file already exists, new content is three-way merged into it, so generator updates and local edits usually converge without manual conflict handling (projects can opt for plain overwrite instead).

Adding is resyncing: `target add` and `feature add` overwrite the vendored copies from their recorded source. Hand-edits to those copies are what `voxgig-sdkgen doctor` exists to catch: it reports forked components, edited template masters, stale files and missing files, welcomes additive components, and exits non-zero for CI.

## Where to go next

- [SDK Generator](https://voxgig.com/sdk)
- [SDK features](https://voxgig.com/sdk/features)
- [Customization how-to](https://github.com/voxgig/sdkgen/blob/main/docs/how-to/customize-and-propagate-templates.md)
- [The demo repo](https://github.com/voxgig-sdk/voxgig-elementdemo-sdk)
- [Contact](https://voxgig.com/contact)
