Skip to content

Versioning & Upgrades

FORGE tracks the version used to generate your project. When a new FORGE release adds features, fixes bugs, or improves generated code, the upgrade system applies those changes to your existing project without overwriting your custom work.

Two Separate Versions

There are two distinct version numbers to be aware of:

┌─────────────────────────────────────────────────────┐
│  1. FORGE CLI Version                               │
│     The tool installed on your machine              │
│     Example: forge v2.1.0                           │
│                                                     │
│  2. Project FORGE Version                           │
│     The version that generated/last upgraded        │
│     your project. Stored in forge.yaml              │
│     and forge.lock                                  │
└─────────────────────────────────────────────────────┘

These versions can differ. You might have FORGE CLI v2.1.0 installed, but your project might have been created with v2.0.0. The upgrade system bridges this gap.

Version Tracking

forge.yaml

The project configuration stores the FORGE version:

yaml
# forge.yaml
name: myapp
forge_version: 2.0.0
backend: rust
frontend: nextjs
# ...

forge.lock

The lock file contains detailed version and integrity information:

yaml
# forge.lock
forge_version: 2.0.0
created_at: 2026-01-20T10:00:00Z
last_upgraded: 2026-01-20T10:00:00Z

templates:
  base: 2.0.0
  crm: 1.0.0          # if CRM module installed

checksums:
  migrations: sha256:abc123...
  seeders: sha256:def456...

files:
  "apps/api/src/routes/mod.rs":
    type: managed
    checksum: sha256:def456

  "apps/web/src/app/layout.tsx":
    type: template
    original_checksum: sha256:ghi789
    current_checksum: sha256:ghi789

TIP

Always commit forge.lock to version control. This ensures every team member works with the same FORGE version context, and upgrades can be applied consistently.

Semantic Versioning

FORGE follows Semantic Versioning:

MAJOR.MINOR.PATCH
  │     │     │
  │     │     └── Bug fixes, no breaking changes
  │     └──────── New features, backwards compatible
  └────────────── Breaking changes, requires migration

What Constitutes a Breaking Change

Change TypeBreaking?Example
New CLI commandNoAdding forge deploy:k8s
New API endpointNoAdding GET /api/v1/stats
Change API response formatYesChanging { user: {...} } to { data: {...} }
Change database column nameYesRenaming users.name to users.full_name
Remove CLI commandYesRemoving a deprecated command
Change default behaviorYesChanging default auth from email to mobile

Checking for Upgrades

Before upgrading, check what has changed:

bash
forge upgrade:check

Output:

Current project version: 2.0.0
Latest FORGE version:    2.1.0
Upgrade type:            minor

Changes in 2.1.0:
  + Added RTL language support
  + Added API key rate limiting
  + Improved audit logging
  + 1 new migration

No breaking changes.
Run `forge upgrade:apply` to apply.

WARNING

Always read the changelog before upgrading. For major version upgrades, review the BREAKING_CHANGES.md document carefully and plan the upgrade during a development window.

The Upgrade Process

Running forge upgrade:apply follows a structured six-step process:

┌─────────────────────────────────────────────────┐
│ 1. VERSION CHECK                                │
│    Read forge.lock → compare with latest        │
│    Determine upgrade type (major/minor/patch)   │
├─────────────────────────────────────────────────┤
│ 2. COMPATIBILITY CHECK                          │
│    Verify custom code doesn't conflict          │
│    Check template and module compatibility       │
├─────────────────────────────────────────────────┤
│ 3. BACKUP                                       │
│    Backup forge.yaml, forge.lock                │
│    Database backup (pg_dump)                    │
│    Create git commit or stash                   │
├─────────────────────────────────────────────────┤
│ 4. APPLY MIGRATIONS                             │
│    Run new database migrations                  │
│    Update forge.lock checksums                  │
├─────────────────────────────────────────────────┤
│ 5. UPDATE CODE                                  │
│    Auto-update managed files                    │
│    Prompt for customized template files          │
│    Add new files from the upgrade               │
├─────────────────────────────────────────────────┤
│ 6. VERIFY                                       │
│    Run tests (forge test)                       │
│    Run linting (forge lint)                     │
│    Health check (forge doctor)                  │
│    Update forge.lock with new version           │
└─────────────────────────────────────────────────┘

File Classification

FORGE classifies every generated file into one of three categories, which determines how it behaves during upgrades:

Core Files

Files that you own. FORGE never touches these after initial generation.

apps/api/src/services/*.rs        # Your business logic
apps/web/src/components/custom/   # Your custom components

FORGE tracks the original checksum but does not compare or update these files. You are free to modify them however you wish.

Managed Files

Files that FORGE owns. These are auto-updated during upgrades.

apps/api/src/routes/mod.rs        # Route registration
apps/api/migrations/*.sql         # Database migrations (immutable)

Managed files include a header comment:

rust
// FORGE MANAGED - DO NOT EDIT
// This file is auto-generated and will be overwritten during upgrades.

WARNING

Do not manually edit managed files. Your changes will be overwritten on the next upgrade. If you need to customize routing or other managed concerns, use the extension points FORGE provides (e.g., custom route files that are imported by the managed router).

Template Files

Files that may need merging. FORGE generated them, but you might have customized them.

apps/web/src/app/layout.tsx       # You might have added custom headers
apps/admin/src/components/Sidebar.tsx  # You might have added menu items
docker-compose.yml                # You might have added services

FORGE tracks both the original checksum (when generated) and the current checksum. During an upgrade:

  • If checksums match (you did not modify it): auto-update safely
  • If checksums differ (you customized it): prompt for action

Handling Customized Files

When a template file was modified by you and the upgrade also needs to change it, FORGE presents an interactive prompt:

┌─────────────────────────────────────────────────────────────────┐
│ apps/web/src/app/layout.tsx                                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ - import { Inter } from 'next/font/google'                     │
│ + import { Inter, Cairo } from 'next/font/google'  // RTL font │
│                                                                 │
│   export default function RootLayout({ children }) {           │
│ -   return <html lang="en">                                    │
│ +   return <html lang={locale} dir={direction}>                │
│                                                                 │
│ Your changes:                                                   │
│ + Added custom header component on line 15                     │
│ + Added analytics script on line 42                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

What would you like to do?
  [A] Accept new version (your changes will be lost)
  [K] Keep your version (skip this upgrade change)
  [M] Merge (open in editor for manual merge)
  [D] Show full diff
  [S] Skip for now

This ensures you never lose custom work without explicit consent.

Upgrade Commands

forge upgrade:apply

The primary upgrade command:

bash
# Upgrade to latest compatible version
forge upgrade:apply

# Upgrade to a specific version
forge upgrade:apply --version=2.1.0

# Preview changes without applying
forge upgrade:apply --dry-run

# Skip creating a backup
forge upgrade:apply --no-backup

forge upgrade:check

Check for available upgrades without making changes:

bash
forge upgrade:check

forge upgrade:rollback

Undo the last upgrade:

bash
# Rollback to the previous version
forge upgrade:rollback

# Rollback to a specific version
forge upgrade:rollback --version=2.0.0

The rollback process:

  1. Restores forge.yaml and forge.lock from backup
  2. Rolls back database migrations added by the upgrade
  3. Reverts code changes using the git history
  4. Verifies the application still passes tests

forge upgrade:history

View the upgrade history for the project:

bash
forge upgrade:history

Output:

Upgrade History for myapp
─────────────────────────

Version   Date                 Type     Status
───────   ──────────────────   ──────   ──────
2.0.0     2026-01-15 10:00     initial  success
2.0.1     2026-01-18 14:30     patch    success
2.1.0     2026-01-22 09:15     minor    success

forge doctor

Verify project health after an upgrade:

bash
forge doctor

Output:

FORGE Doctor - Project Health Check

  ✓ forge.yaml valid
  ✓ forge.lock integrity verified
  ✓ All migrations applied
  ✓ Backend compiles (cargo check)
  ✓ Frontend builds (npm run build)
  ✓ API contract satisfied
  ✓ Required pages present
  ✓ Permissions seeded correctly

All checks passed. Project is healthy.

Minor Upgrade Example

A typical minor version upgrade (no breaking changes):

bash
$ forge upgrade:apply

Checking for updates...
  Current: 2.0.0
  Latest:  2.1.0 (minor)

Changes in 2.1.0:
  + Added RTL language support
  + Added API key rate limiting
  + Improved audit logging
  + 1 new migration

No breaking changes.

Proceed with upgrade? [Y/n] Y

Creating backup...
Running migrations...
Updating managed files...
Updating forge.lock...

Successfully upgraded to 2.1.0

Run `forge test` to verify everything works.

Major Upgrade Example

A major version upgrade with breaking changes requires more care:

bash
$ forge upgrade:apply --version=3.0.0

MAJOR VERSION UPGRADE

This upgrade includes BREAKING CHANGES:
  - API response format changed
  - Permission format changed (users.view  user:read)
  - Removed deprecated forge:ssl command

Required manual actions after upgrade:
  1. Update frontend API calls to new response format
  2. Run permission migration script
  3. Update any scripts using forge:ssl

Read full changelog: https://forge.dev/changelog/3.0.0

Proceed? [y/N] y

Creating backup...
Running pre-upgrade checks...

Step 1/5: Migrate database schema
  Running 5 migrations...

Step 2/5: Update API handlers
  12 files updated

Step 3/5: Migrate permissions
  Converting 24 permissions...

Step 4/5: Update frontend
  3 files need manual merge

Step 5/5: Verify
  Running tests...
  Running lints...

Upgrade to 3.0.0 complete!

Manual steps remaining:
  - Review and merge 3 conflicted files
  - Update custom API integrations (see migration guide)

Best Practices

PracticeReason
Always back up firstUse forge upgrade:apply (creates backup by default) or commit to git before upgrading
Upgrade staging firstTest the upgrade on a staging environment before production
Read the changelogforge upgrade:check shows what changed -- read it
Upgrade incrementallyGo 2.0 to 2.1 to 2.2 to 3.0, not 2.0 to 3.0 directly
Commit forge.lockKeep it in version control so the whole team stays in sync
Run tests after upgradeforge test && forge lint catches regressions
Avoid editing managed filesFiles marked FORGE MANAGED will be overwritten
Run forge doctorPost-upgrade health check catches issues early

TIP

The safest upgrade workflow: commit all changes to git, run forge upgrade:apply, run forge test, and if anything fails, use git reset to return to the pre-upgrade state. This gives you a clean rollback path independent of FORGE's built-in rollback mechanism.

Released under the MIT License.