> For the complete documentation index, see [llms.txt](/llms.txt)

# Custom code

Generated SDKs cover the API, but real projects need a little hand-written code too — a convenience
wrapper, an extra helper, a tweak to a generated method. Glotto is built so your code **survives
regeneration**. There are two mechanisms:

1. The **customer-owned extension directory** — `lib/` in most SDKs and
   `Sources/<Module>/Custom/` in Swift. Shipped today.
2. **Patch preservation** — three-way merge of edits to *generated* files, in the release PR and (opt-in) locally.

For anything you write from scratch, prefer that extension directory: it's where preservation is
guaranteed.

## The customer-owned extension directory

Every generated SDK has an extension directory that is yours. Most engines use **`lib/`**; Swift
uses **`Sources/<Module>/Custom/`**, inside its conventional SwiftPM target. The contract is
enforced by `glotto generate` and drift detection the same way for every language:

- **Customer-owned, write-if-absent.** Glotto seeds the directory once with an entry-point stub,
  then **never overwrites that customer-owned file**. Every managed file is regenerated normally,
  but your extension is left exactly as you left it.
- **Excluded from drift.** Drift detection ignores customer-owned files on both sides, so an edit
  there never shows up as drift or blocks a release — the extension is not part of the
  "regenerate must match" contract.
- **A stable import target.** The entry-point stub (TypeScript's `lib/index.ts`, Python's
  `lib/__init__.py`, Swift's `Sources/<Module>/Custom/Custom.swift`, …) gives you a fixed place to
  export from, and its header comment tells you how code you add there reaches the SDK's surface in
  that language.

**The half of the tree Glotto never writes twice**

One TypeScript target, and one real generate run over it. The stub below is the file Glotto writes once and then never writes again; the method beside it is regenerated on every run, under the checksum that decides which of the two you are editing.

Derived from `examples/custom-code-lib/inputs` — every byte below is sliced from that demo or from one real generate run over it.

**Your glotto.yml — one TypeScript target, and not a word about custom code** (`examples/custom-code-lib/inputs/glotto.yml` `targets`)

```yaml
targets:
  typescript: {}
```

**glotto generate**

**What Glotto seeds ONCE — src/lib/index.ts, yours from then on** (`typescript/src/lib/index.ts` `whole file`)

```ts
// Custom code — never overwritten by `glotto generate`.
//
// This file, and everything else under `lib/`, is yours. `glotto generate`
// writes it once and then leaves it untouched on every subsequent run, and
// drift detection ignores `lib/` entirely — so helpers, overrides, and
// extensions you add here survive regeneration. Re-export them from this entry
// point to keep a single import surface for your custom code.

export {};
```

sha256 `066b46389fdd95f09343610f9fdb02d97e8c50f27626cd164f919fe40f029ab8`

**What Glotto owns — regenerated every run, under the checksum that guards your edits** (`typescript/src/resources/widgets.ts` `WidgetsResource.createWidget`)

```ts
  createWidget(params: NewWidget, options?: RequestOptions): Promise<Widget> {
    return this.core.request<Widget>('POST', '/widgets', { ...options, body: params, contentType: 'application/json' });
  }
```

generated-checksum `405b8140007456df5543f12bcfa55e05b969d62b5cefcbe186d4f484ee1bd247`

Put helpers, wrappers, and hand-authored code in the extension directory, and it is preserved on
every regenerate. Anything you expose from the stub reaches the SDK's public surface according to
that language's normal package conventions.

> **Upgrading an existing Swift SDK:** if Glotto finds the former `lib/Custom.swift` and no file at
> `Sources/<Module>/Custom/Custom.swift`, the next `glotto generate` copies its contents exactly to
> the SwiftPM target and retains the legacy file as a backup for you to remove after review. If both
> files already exist, Glotto leaves both untouched and prints the paths to reconcile; it never
> chooses one customer-owned copy over the other.

> **Every language, on the SDK's surface:** the `lib/` machinery (write-if-absent + drift
> exclusion) is engine-agnostic, every SDK language seeds an entry-point stub, and custom code
> joins the SDK's public surface per language:
> TypeScript and React Native re-export it as `lib`; Swift compiles `Custom/` as part of its module;
> Java, Kotlin, Rust, C#, Dart, and Elixir compile `lib/` into the SDK artifact; Ruby loads it with
> `require "glotto"`; and the Go, Python, and PHP stubs document the exact import path to use.

## Editing generated files

Sometimes you need to change a **generated** file directly. Glotto's rule is simple: **it never
silently overwrites your edits.**

Every generated file carries a checksum comment over the bytes Glotto produced — the
`generated-checksum` stamped under the emitted pane above is the real one for that file, read out of
the run that produced it rather than written here.

On the next regenerate, Glotto compares that checksum to the file's current contents. If they
match, the file is pristine and is regenerated freely. If they differ, you've hand-edited it — so
Glotto performs a **three-way merge** (your version against the old and new generator output) and,
on any conflict, writes standard conflict markers and **surfaces them in the release pull request**
for you to resolve, rather than clobbering your change.

> **How it runs today:** the checksum marker ships on every generated SDK language, the
> release-PR flow does the full three-way merge automatically, and locally `glotto generate`
> preserves your edited file untouched — or truly merges it when you opt in with
> [`--merge`](/docs/cli#glotto-generate).
> Even the generated `README.md` is covered — its checksum rides in an HTML comment that's
> invisible in the rendered README, so badges and prose you add survive regeneration.
> The customer-owned extension remains the simplest home for hand-authored code — no merge to
> think about at all.

## Which should I use?

| You want to… | Use |
| --- | --- |
| Add new helpers, wrappers, or utilities | The customer-owned extension — always preserved |
| Re-export or extend generated types | The customer-owned extension, importing generated types normally |
| Change the behavior of a generated method | Edit the generated file (preserved; merged in the release PR or with `--merge`) — or wrap it in the extension |

See [Drift detection](/docs/drift-detection) for how customer-owned files are excluded from the drift gate. The
[CLI reference](/docs/cli) documents the commands that enforce this contract —
[`glotto generate`](/docs/cli#glotto-generate) (whose `--force` overwrites managed files with local
edits) and [drift detection](/docs/drift-detection).
