SDKs
Persistent edits: Add custom code anywhere in your generated SDKs
Thomas Rooney
December 13, 2025 - 4 min read
Speakeasy generates production-ready SDKs and Terraform providers from OpenAPI specifications, with extensive configuration options through hooks, gen.yaml settings, and OpenAPI extensions
With persistent edits, you can:
- Add utility methods, custom properties, and business logic to any generated file
- Modify configuration files like package.json or pyproject.toml directly
- Extend your SDK without waiting for Speakeasy to add new configuration options
The generation ownership problem
Speakeasy’s code generator has always taken an opinionated approach: the files we generate, we own. This ensures deterministic output and predictable behavior. Given the same configuration, you always get the exact same SDK.
This approach has served us well, but it comes with a constraint. When users wanted to add functionality that wasn’t supported through our configuration system, they had two options:
- Wait for us to add a new configuration option
- Work around it by maintaining changes in separate files
Neither option was ideal. Adding configuration for every use case creates complexity, and maintaining changes separately breaks the convenience of having everything in one place.
What teams really wanted was simple: make a change to the generated code, and have that change persist.
How persistent edits work
Persistent edits removes the restrictions on where you can make changes to Speakeasy-generated code. The concept is straightforward: modify any file in your generated SDK, and Speakeasy will maintain those changes as long as they don’t conflict with updates we’re making.
The conflict detection works like git merge. If you modify a line and we later regenerate code that touches the same line, you’ll see a conflict. But if your changes and ours touch different parts of the file, both changes coexist seamlessly.
Enabling persistent edits
The first time you modify a generated file and run Speakeasy, you’ll see a prompt:
⚠ Modified files detected
╭─────────────────────────────────────────────────────╮
│ We've detected changes to files that Speakeasy │
│ manages. Would you like to enable persistent edits │
│ to maintain these changes? │
│ │
│ Modified files: │
│ - src/sdk/payments.ts │
│ - package.json │
╰─────────────────────────────────────────────────────╯
Enable persistent edits? (Y/n)Choose yes, and Speakeasy adds persistentEdits: { enabled: true } to your gen.yaml. From that point forward, all your changes persist automatically.
Real-world use cases
Adding utility methods
One of the most common requests we’ve seen is adding helper methods to generated models. With persistent edits, you can add methods directly to the generated classes:
export class Payment {
id: string;
amount: number;
currency: string;
status: PaymentStatus;
// Generated code above
// Your custom method below
/**
* Convert payment to invoice format
*/
toInvoiceItem(): InvoiceItem {
return {
description: `Payment ${this.id}`,
amount: this.amount,
currency: this.currency,
};
}
/**
* Check if payment requires customer action
*/
needsAction(): boolean {
return (
this.status === PaymentStatus.RequiresAction ||
this.status === PaymentStatus.RequiresConfirmation
);
}
}These methods persist across regenerations. Add a new field to your OpenAPI spec, regenerate, and your custom methods remain intact.
Modifying configuration files
Want to add a dependency that Speakeasy doesn’t know about? Just edit package.json directly:
{
"name": "@acme/payments-sdk",
"version": "1.0.0",
"dependencies": {
"axios": "^1.6.0",
"zod": "^3.22.0",
"aws-sdk": "^2.1.0" // Your custom dependency
}
}Speakeasy maintains this change. When we update other parts of package.json (like version numbers or our dependencies), your aws-sdk entry stays.
Extending SDK initialization
Some teams need custom authentication providers or specialized configuration. Add them directly to the SDK constructor:
import { AWSAuth } from "./custom/aws-auth";
export class PaymentsSDK {
private client: HTTPClient;
private awsAuth?: AWSAuth;
constructor(config: SDKConfig) {
this.client = new HTTPClient(config);
// Your custom initialization
if (config.awsAuth) {
this.awsAuth = new AWSAuth(config.awsAuth);
this.client.interceptors.request.use(
this.awsAuth.signRequest.bind(this.awsAuth),
);
}
}
}Getting started
Persistent edits is available today for all Speakeasy users across SDKs and Terraform providers.
To enable persistent edits on an existing SDK:
- Make a change to any generated file
- Run
speakeasy run - When prompted, choose Yes to enable persistent edits
- Commit the updated gen.yaml with
persistentEdits: { enabled: true }
For new SDKs, you can enable it immediately by adding the flag to gen.yaml:
configVersion: 2.0.0
generation:
sdkClassName: PaymentsSDK
maintainOpenAPIOrder: true
persistentEdits:
enabled: trueOnce enabled, any modifications you make to generated files will persist across regenerations. The feature works locally and in CI/CD, with no additional setup required.
Persistent edits represents our vision for how code generation should work: deterministic and reliable, but flexible enough to meet you where you are. Generated code shouldn’t be a black box you work around. It should be a foundation you can build on.
Questions about persistent edits or need help with a specific use case? Book time with our team