Skip to Content

Patch files

Patch files capture modifications to generated SDKs as standalone unified-diff artifacts. Drop .patch files into .speakeasy/patches/, and Speakeasy reapplies them after every generation.

Use patch files when:

  • The SDK is not checked into a Git repository, or Git tooling is not available in the generation environment.
  • You want each edit captured as a separate, code-reviewable diff artifact instead of an in-place 3-way merge.

Patch files compared to custom code

Patch filesCustom code
Git repo requiredNoYes
Edits live in.speakeasy/patches/*.patchThe generated files themselves
File create / delete / renameSupported (regular files)Supported
Best forReviewable diff artifactsIn-place editing with automatic preservation

Creating a patch file

Suppose Speakeasy generates the following TypeScript model:

src/models/payment.ts
export class Payment { id: string; amount: number; currency: string; status: PaymentStatus; }

Suppose the goal is to drop the id field, pin currency to "USD", and add a needsAction() helper — all surviving every regeneration:

1. Back up the pristine generated file before editing, so a clean baseline exists for the diff:

cp src/models/payment.ts src/models/payment.ts.orig

2. Edit the generated file directly.

src/models/payment.ts
export class Payment { amount: number; currency: "USD" = "USD"; status: PaymentStatus; needsAction(): boolean { return this.status === PaymentStatus.RequiresAction; } }

3. Produce a unified diff against the pristine generated content.

diff -u src/models/payment.ts.orig src/models/payment.ts > .speakeasy/patches/src/models/payment.ts.patch

Or inside a Git repo:

git diff src/models/payment.ts > .speakeasy/patches/src/models/payment.ts.patch

The patch path under .speakeasy/patches/ mirrors the generated file’s path relative to the SDK root. So src/models/payment.ts becomes .speakeasy/patches/src/models/payment.ts.patch:

.speakeasy/patches/src/models/payment.ts.patch
diff --git a/src/models/payment.ts b/src/models/payment.ts --- a/src/models/payment.ts +++ b/src/models/payment.ts @@ -1,6 +1,9 @@ export class Payment { - id: string; amount: number; - currency: string; + currency: "USD" = "USD"; status: PaymentStatus; + + needsAction(): boolean { + return this.status === PaymentStatus.RequiresAction; + } }

4. Restore the pristine file so it is back to its unedited state.

5. Re-run speakeasy run. Speakeasy applies the patch and writes the patched file. All three edits — the removed id field, the pinned currency, and the needsAction() method — now persist across regenerations.

6. Commit .speakeasy/patches/ to source control alongside the SDK. Patches are the durable record of edits — losing them means losing the customizations on the next regeneration.

Handling conflicts

When the generated content changes in a way that the patch can no longer apply cleanly, Speakeasy:

  • Rebases the patch onto the new generated output.
  • Writes any unresolved hunks as Git-style conflict markers (<<<<<<<, =======, >>>>>>>) into the affected file.
  • Marks the generation step as failed and lists the conflicted files.

To resolve:

  1. Open each conflicted file and edit it to the desired final content.

  2. Regenerate the patch from the resolved file:

    git diff <file> > .speakeasy/patches/<file>.patch
  3. Discard the working-copy edits and re-run speakeasy run.

Next steps

  • See the technical reference for the apply pipeline, path normalization rules, and error semantics.
  • For in-place editing with automatic merging, see custom code.

Last updated on