For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Book a demoLog inStart for free
  • Overview
    • Introduction
    • How it works
    • Quickstart
    • Customer showcase
  • Working with SDKs
    • Project structure
    • Adding custom code
    • Migrating to Replay
    • Capabilities
  • Generators
  • Reference
    • generators.yml
Checking status...
SOC2Soc 2 Type II
© 2026 Fern • Birch Solutions, Inc., a Postman company

Documentation

SDKsDocsAsk FernCLI Reference

API Definitions

OpenAPIAsyncAPIOpenRPCgRPC

Resources

BlogSupportPricing

Company

Brand KitPrivacy PolicyTerms of Service
LogoLogo
Book a demoLog inStart for free
On this page
  • Full-file ownership with .fernignore
  • Line-level edits with Replay
  • Enable Replay
  • Disable Replay
  • Customization patterns by language
Working with SDKs

Adding custom code

||View as Markdown|
Was this page helpful?
Edit this page
Previous

Project structure

Next

Migrating to Replay

Fern-generated SDKs are designed to be extended with custom logic, methods, and dependencies. If you want your SDK to do more than just make basic API calls (like combining multiple calls, processing data, adding utilities), you can add custom code that lives in harmony with the generated code.

Fern provides two complementary tools for keeping your customizations safe across regenerations:

  • .fernignore — Full-file ownership. The generator stops touching listed files entirely. Use for fully hand-written modules, READMEs, or custom workflows. Trade-off: you also stop receiving generator updates to those files.
  • Replay — Line-level edits. Keep generated files under generator control, and reapply your edits via 3-way merge on every regeneration.

Full-file ownership with .fernignore

.fernignore applies only to SDK generation. It has no effect on Fern Docs builds.

Use .fernignore to protect files you own end-to-end from being overwritten during SDK regeneration.

Add your custom files to the SDK repository and list them in .fernignore. A .fernignore file is automatically created in your SDK repository when you use GitHub publishing.

Your .fernignore file might look something like this:

.fernignore
1# Documentation and licensing
2README.md
3LICENSE
4
5# Custom workflows
6.github/workflows/test.yml
7.github/workflows/ci.yml
8
9# Custom code
10src/CustomClient.ts

For another real-world example, see Cohere’s .fernignore file for their TypeScript SDK.

You’ll have a separate .fernignore file for each of your SDKs:

company-repo# Top-level repo for all SDKs
fern
typescript-sdk-repo# Repository for a TypeScript SDK
.fernignore
.github
src
python-sdk-repo
.fernignore
.github
src

Line-level edits with Replay

Replay automatically preserves the edits you make to your generated SDK across regenerations. When you commit a change to generated code, Replay scans your repo’s history since the last [fern-generated] commit and stores each customer commit as a tracked patch in .fern/replay.lock. On the next fern generate, those patches are reapplied to the freshly generated SDK via 3-way merge, and the result lands as a [fern-replay] commit on top of [fern-generated] in the regeneration PR:

Regeneration PR
* abc123 (HEAD -> main) [fern-replay] Apply customizations
* 789abc [fern-generated] Update SDK to spec rev 0451
* 234bcd Add helpers on top of User type
* ...

If the generator and your customization changed the same lines, Replay reports the conflict in the PR body. Run fern replay resolve locally to walk through it.

Enable Replay

For SDKs on pull-request output mode, run fern generate to turn Replay on globally. You’ll see that .fern/replay.lock is committed to your SDK repo. From that point on, edits you make to generated files are tracked automatically.

To enable Replay on an SDK that’s currently on release or push mode, switch to pull-request mode via the migration guide.

Disable Replay

To disable Replay, set replay.enabled: false at the top level of generators.yml. See the replay reference.

Customization patterns by language

Each SDK generator has its own conventions for adding custom code: how to extend the generated client, where helpers go, how to declare dependencies. See the guide for your language:

TypeScript logo
TypeScript
Python
Go
Java
.NET
PHP
Ruby