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.
预约演示登录免费开始
  • 使用 SDK
    • SDK 概述
    • SDK 如何工作
    • Quickstart
    • Customer showcase
  • 使用 SDK
    • 项目结构
    • 添加自定义代码
    • Migrating to Replay
    • 功能特性
  • 参考
  • 资源
    • 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
预约演示登录免费开始
在本页
  • What changes
  • Before you start
  • Phase 1: Move publishing secrets to the SDK repo
  • Phase 2: Switch output mode
  • Phase 3: Decouple publishing from generation (optional)
  • Phase 4: First generation with Replay
  • Phase 5: Validate
  • Rollback
  • Troubleshooting
  • Known caveats
使用 SDK

Migrating to Replay

||以 Markdown 格式查看|
此页面是否有帮助?
在仪表板中编辑
上一个

添加自定义代码

下一个

功能特性

This guide migrates an SDK from release or push output mode to pull-request output mode — the mode required to enable Fern Replay. Only follow it if your SDK is currently on release or push mode and you want to switch in order to use Replay. SDKs already using pull-request mode have Replay on by default; no migration is needed.

What changes

  • SDK updates arrive as PRs instead of direct pushes to main.
  • Customizations to generated code survive regeneration via 3-way merge.
  • Version bumps are computed from pure generator output, never contaminated by customizations.
  • Publishing is decoupled from generation, so you control when to release.

Before you start

  • Install the Fern GitHub App on your SDK repositories.
  • Update to the latest Fern CLI: fern upgrade.
  • Update to the latest SDK generator versions: fern generator upgrade.

Phase 1: Move publishing secrets to the SDK repo

Fern sets GitHub Actions secrets in your SDK repo on every generation. When you switch to pull-request output mode, that write would clobber any secrets you set directly. To avoid this, move secret ownership from the config repo to the SDK repo before flipping modes.

For each SDK repo:

1

Identify the publishing secrets

Find which secrets your generators.yml references for publishing:

  • Python: PYPI_USERNAME, PYPI_PASSWORD
  • TypeScript / npm: NPM_TOKEN
  • Java / Maven: MAVEN_USERNAME, MAVEN_PASSWORD, MAVEN_SIGNATURE_KID, MAVEN_SIGNATURE_PASSWORD, MAVEN_SIGNATURE_SECRET_KEY
  • Ruby: RUBY_GEMS_API_KEY
  • C# / NuGet: NUGET_API_KEY
  • Rust / Crates: CRATES_TOKEN
2

Add credentials to the SDK repo

Add the real publish credentials directly to the SDK repo: Settings → Secrets and variables → Actions → New repository secret.

3

Remove credentials from generators.yml

Remove the publish credential values from the config repo’s generators.yml:

generators.yml
1# BEFORE
2groups:
3 python-sdk:
4 generators:
5 - name: fernapi/fern-python-sdk
6 version: "..."
7 github:
8 repository: customer/python-sdk
9 mode: pull-request
10 output:
11 pypi:
12 username: $PYPI_USERNAME
13 password: $PYPI_PASSWORD
14
15# AFTER (remove the output/pypi block entirely)
16groups:
17 python-sdk:
18 generators:
19 - name: fernapi/fern-python-sdk
20 version: "..."
21 github:
22 repository: customer/python-sdk
23 mode: pull-request
4

Verify secrets are preserved

Run a generation. Confirm the SDK repo’s secrets weren’t overwritten by checking the “Last updated” timestamp under SDK repo → Settings → Secrets.

Phase 2: Switch output mode

In generators.yml:

generators.yml
1github:
2 repository: customer/python-sdk
3 mode: pull-request # was: mode: release (or: mode: push)

If you use version: AUTO, no other changes are needed. Autoversioning runs as part of the generator-cli pipeline and diffs pure generator output, so customer customizations never contaminate the version diff.

Phase 3: Decouple publishing from generation (optional)

To control publishing on your own schedule rather than on every Fern generation, keep your publish workflow out of Fern’s generation cycle:

1

Add the workflow to .fernignore

.fernignore
.github/workflows/ci.yml
2

Change the workflow trigger

Switch from push-to-main to manual or release-tagged:

.github/workflows/ci.yml
1# Instead of:
2on:
3 push:
4 branches: [main]
5
6# Use:
7on:
8 workflow_dispatch:
9 release:
10 types: [published]
3

Update secret references

Update any secret references if you renamed credentials in Phase 1.

Phase 4: First generation with Replay

1

Run fern generate

Run fern generate --group <group-name> from the config repo (or trigger via your existing CI).

2

Confirm the lockfile was created

The first run auto-creates .fern/replay.lock. Replay tracks customer commits to generated files from this point on.

3

Review the resulting PR

The PR contains:

  • [fern-generated]: pure generator output
  • [fern-replay]: patches re-applied (empty on first run, since no patches exist yet)
  • Updated .fern/replay.lock
4

Squash-merge the PR

The next generation re-anchors correctly even after the squash.

Phase 5: Validate

After the first generation and merge, confirm the following:

  • A PR was created (not a direct push to main).
  • No unintended package release was triggered.
  • SDK code is correct and passes CI.
  • .fern/replay.lock exists in the SDK repo.
  • .fernignore contains replay.lock (and replay.yml).

After your first real customization, verify Replay’s behavior end-to-end:

  • You edit a generated file, commit, and merge to main.
  • The next fern generate detects the patch (PR body shows patches detected: 1).
  • The customization survives regeneration via a clean 3-way merge.
  • .fern/replay.lock shows the patch stored.

Rollback

Replay never modifies files destructively. Your main branch always has correct code, so rolling back is straightforward.

Quick disable. To stop Replay while staying in pull-request mode, set replay.enabled: false in your generators.yml (see the replay reference). The next fern generate skips the patch detection and application phase; PRs land in the same shape as before, just without the [fern-replay] commit.

Full revert to release or push mode:

1

Switch mode back in generators.yml

generators.yml
1github:
2 repository: customer/python-sdk
3 mode: release # or mode: push
2

Re-add publish credentials to the config repo

Re-add the credentials you removed in Phase 1.

3

Clean up Replay state in the SDK repo

  • Delete .fern/replay.lock
  • Delete .fern/replay.yml
  • Delete the fern-generation-base tag if it exists
4

Close any open fern-bot PRs from PR mode

Troubleshooting

CommandEffect
fern generate --no-replaySkip patch application for one generation. Generation still creates [fern-generated]; patches aren’t applied. Useful for debugging.
fern replay forgetUntrack patches by ID, by pattern, or all at once. The next generation overwrites those files.

Known caveats

  • Closed-without-merge replay PRs. If a replay PR is closed without merging, the next generation re-derives its anchor from the current branch history. No manual cleanup needed.
  • Force pushes and rewritten history. Replay re-derives its scan anchor from git log on every run, so force-pushed branches continue to work and existing patches still apply correctly.