Skip to content

Configuration โ€‹

Complete guide to configuring Relizy.

Configuration File โ€‹

Create a configuration file in your project root:

ts
import { defineConfig } from 'relizy'

export default defineConfig({
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },
})
js
import { defineConfig } from 'relizy'

export default defineConfig({
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },
})
json
{
  "monorepo": {
    "versionMode": "selective",
    "packages": ["packages/*"]
  }
}
json
{
  "name": "my-monorepo",
  "version": "1.0.0",
  "relizy": {
    "monorepo": {
      "versionMode": "selective",
      "packages": ["packages/*"]
    }
  }
}
yml
monorepo:
  versionMode: selective
  packages:
    - packages/*
toml
[monorepo]
versionMode = "selective"
packages = [ "packages/*" ]

Supported Formats โ€‹

Relizy supports multiple configuration formats. It loaded with c12, check the documentation for more details.

  • relizy.config.ts (recommended)
  • relizy.config.js
  • relizy.config.mjs
  • relizy.config.json
  • relizy.config.yaml
  • relizy.config.yml
  • relizy.config.toml
  • And more...

Zero Configuration โ€‹

Relizy works out of the box without any configuration (for single package):

bash
relizy release

Configuration is only needed for:

  • Monorepo settings (needs monorepo section with versionMode and packages glob patterns to find your packages)
  • Custom commit types
  • Multiple release strategies

Quick Start โ€‹

Single Package โ€‹

No configuration needed! Just run:

bash
relizy release --minor

Monorepo - Basic โ€‹

ts
// relizy.config.ts
export default defineConfig({
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
  },
})

Monorepo - Advanced โ€‹

ts
// relizy.config.ts
export default defineConfig({
  projectName: 'My project', // replace the name in your root package.json (Useful for Twitter (X) and Slack posts)
  monorepo: {
    versionMode: 'selective',
    packages: ['packages/*'],
    ignorePackageNames: ['pacakge-a'],
  },
  bump: {
    dependencyTypes: ['dependencies', 'devDependencies'],
  },
  types: {
    feat: { title: '๐ŸŽ‰ Features', semver: 'minor' },
    fix: { title: '๐Ÿ› Fixes', semver: 'patch' },
  },
  publish: {
    access: 'public',
    tag: 'latest',
  },
})

Configuration Sections โ€‹

SectionDescription
monorepoMonorepo-specific settings
typesCommit type customization
bumpVersion bump settings
changelogChangelog generation settings
publishNPM publishing options
releaseRelease workflow settings
aiAI-enhanced changelogs and announcements
socialSocial media integration (Twitter, Slack)
prCommentPR comment settings
hooksLifecycle hooks for custom scripts
multiple-configsUsing multiple configuration files

TypeScript Support โ€‹

Get full IntelliSense with TypeScript:

ts
import { defineConfig } from 'relizy'

export default defineConfig({
  // Full type checking and autocomplete
  monorepo: {
    versionMode: 'selective', // โ† Autocompleted
  },
})

Multiple Configurations โ€‹

Use different configs for different workflows:

bash
# Use default config
relizy release

# Use staging config
relizy release --config relizy.staging

# Uses relizy.staging.config.ts

Learn more in Multiple Configs.

Default Configuration โ€‹

If no config file exists, Relizy uses these defaults:

ts
const defaultConfig = {
  cwd: process.cwd(),
  types: {
    feat: { title: '๐Ÿš€ Enhancements', semver: 'minor' },
    perf: { title: '๐Ÿ”ฅ Performance', semver: 'patch' },
    fix: { title: '๐Ÿฉน Fixes', semver: 'patch' },
    refactor: { title: '๐Ÿ’… Refactors', semver: 'patch' },
    docs: { title: '๐Ÿ“– Documentation', semver: 'patch' },
    build: { title: '๐Ÿ“ฆ Build', semver: 'patch' },
    types: { title: '๐ŸŒŠ Types', semver: 'patch' },
    chore: { title: '๐Ÿก Chore' },
    examples: { title: '๐Ÿ€ Examples' },
    test: { title: 'โœ… Tests' },
    style: { title: '๐ŸŽจ Styles' },
    ci: { title: '๐Ÿค– CI' },
  },
  templates: {
    // commitMessage / commitBody are resolved based on monorepo.versionMode:
    //   - independent      โ†’ 'chore(release): bump {{packageCount}} packages' + body '{{packageList}}'
    //   - unified/selective โ†’ 'chore(release): bump version to {{newVersion}}' (no body)
    // See: /config/commit-templates for placeholders and examples.
    commitMessage: undefined,
    commitBody: undefined,
    tagMessage: 'Bump version to {{newVersion}}',
    tagBody: 'v{{newVersion}}',
    emptyChangelogContent: 'No relevant changes for this release',
    twitterMessage: '๐Ÿ“ฃ {{projectName}} {{newVersion}} is out!\n\n{{changelog}}\n\n{{releaseUrl}}\n{{changelogUrl}}',
    slackMessage: undefined,
    changelogTitle: '{{oldVersion}}...{{newVersion}}',
  },
  excludeAuthors: [],
  noAuthors: false,
  bump: {
    type: 'release',
    clean: true,
    dependencyTypes: ['dependencies'],
    yes: false,
  },
  changelog: {
    rootChangelog: true,
    includeCommitBody: true,
  },
  publish: {
    private: false,
    args: [],
  },
  tokens: {
    gitlab:
        process.env.RELIZY_GITLAB_TOKEN
        || process.env.GITLAB_TOKEN
        || process.env.GITLAB_API_TOKEN
        || process.env.CI_JOB_TOKEN,
    github:
        process.env.RELIZY_GITHUB_TOKEN
        || process.env.GITHUB_TOKEN
        || process.env.GH_TOKEN,
    twitter: {
      apiKey: process.env.RELIZY_TWITTER_API_KEY || process.env.TWITTER_API_KEY,
      apiKeySecret: process.env.RELIZY_TWITTER_API_KEY_SECRET || process.env.TWITTER_API_KEY_SECRET,
      accessToken: process.env.RELIZY_TWITTER_ACCESS_TOKEN || process.env.TWITTER_ACCESS_TOKEN,
      accessTokenSecret: process.env.RELIZY_TWITTER_ACCESS_TOKEN_SECRET || process.env.TWITTER_ACCESS_TOKEN_SECRET,
    },
    slack:
        process.env.RELIZY_SLACK_TOKEN
        || process.env.SLACK_TOKEN,
    ai: {
      'claude-code': {
        apiKey: process.env.RELIZY_ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY,
        oauthToken: process.env.RELIZY_CLAUDE_CODE_OAUTH_TOKEN || process.env.CLAUDE_CODE_OAUTH_TOKEN,
      },
    },
  },
  scopeMap: {},
  social: {
    twitter: {
      enabled: false,
      onlyStable: true,
    },
    slack: {
      enabled: false,
      onlyStable: true,
    },
  },
  prComment: {
    mode: 'append',
  },
  ai: {
    provider: 'claude-code',
    language: 'en',
    fallback: 'raw',
    providers: {
      'claude-code': { model: 'haiku' },
    },
    providerRelease: { enabled: false },
    social: {
      twitter: { enabled: false },
      slack: { enabled: false },
    },
  },
  release: {
    commit: true,
    publish: true,
    changelog: true,
    push: true,
    clean: true,
    providerRelease: true,
    noVerify: false,
    gitTag: true,
    social: true,
    prComment: true,
  },
  logLevel: 'default',
  detectRewrittenTags: true,
}

Detecting Rewritten Tags โ€‹

When a release tag is created and pushed, then the branch is later rebased, the tag keeps pointing to the old (now orphaned) commit. Resolving a changelog from an orphaned tag spans the whole divergent range (often the entire history since the last stable release, with duplicated commits) and over-bumps packages.

Relizy detects this automatically and recovers safely. Two top-level options control the behavior:

OptionTypeDefaultDescription
detectRewrittenTagsbooleantrueDetect when the from tag is no longer reachable from to and recover.
onRewrittenTagstringautoprompt | ephemeral | rebind | error. Auto = prompt (TTY) / ephemeral (CI/--yes).

A commit is never rewritten; the only possible mutation is moving a tag. See the Rewritten Tags & Rebases guide for the full explanation and the recommended git workflow.

Next Steps โ€‹

Explore specific configuration sections:

Released under the MIT License.