Semifold
Getting Started

Make your first release

Initialize a small repository, record a change, review affected packages, update versions, and publish.

This tutorial follows the normal interactive CLI. You will create Semifold configuration, record one changeset, inspect the packages affected by it, update files, and prepare a registry publish.

Before you start

Use a Git repository whose default branch is main and whose worktree is clean. The example assumes at least one valid Rust package with a Cargo.toml; the same lifecycle applies to other built-in ecosystems.

Install Semifold first if smif --version does not work. The installation guide lists every supported method.

1. Initialize the repository

Run this from the repository root:

smif init

The prompts guide you through:

  1. which package ecosystems to discover;
  2. the base and release branch names;
  3. default changelog categories;
  4. whether to generate GitHub Actions workflows.

For this tutorial, select Rust, keep main and release, accept the default categories, and generate the workflows.

Files created

config.toml
semifold-ci.yaml
semifold-status.yaml

Open .changes/config.toml. Under [packages], confirm that each discovered package has the expected path and resolver. The table key is its stable PackageId, which may differ from the manifest's registry name.

If this repository was already initialized and packages later changed, use smif config sync instead of running init --force again.

2. Make one user-visible change

Change a public API or another behavior that users will notice. Keep the change small enough that its version impact is easy to judge.

Now record the release intent:

smif commit

Choose the changed package, select patch, minor, or major, choose a changelog category, give the changeset a short name such as add-api, and write a user-facing summary.

Semifold creates a file like:

.changes/add-api.md
---
my-package: "minor:feat"
---

Add the public API.

minor requests the version increase. feat chooses the changelog section; it does not select a release channel.

Commit the changeset with the code change so reviewers can evaluate both together.

3. Review affected packages

smif status

What to verify

  • your package appears with the expected current and target versions;
  • its direct reason points to the changeset file named .changes/add-api.md;
  • any additional package has an understandable dependency-propagation reason;
  • the final message says the release plan is ready, not that files were changed.

If a package or version is wrong, stop here. Correct the changeset, package ID, or dependency configuration and run smif status again.

4. Choose the automated or manual path

If smif init generated the GitHub Actions workflows, the recommended path stops using local release commands here:

  1. push the code change and .changes/add-api.md, then merge that pull request into main;
  2. the generated workflow runs smif ci, updates the configured release branch, and creates or refreshes its release pull request;
  3. review the generated versions and changelogs in that release pull request, then merge it into main;
  4. the next workflow run sees no pending changesets and publishes the prepared package versions in dependency order.

Do not also run smif version or smif publish locally for the same release. Continue below only when the repository does not use the generated workflow, or when you are deliberately learning and testing the manual mechanism in a disposable repository.

5. Manually preview and apply version changes

Preview the file and command work first:

smif version --dry-run

The preview does not apply normal version side effects. A configured command runs during the preview only when its configuration explicitly says dry-run = true; such a command must be safe to run repeatedly.

When the preview matches your intent, apply it:

smif version

Semifold updates package versions and eligible internal requirements, writes changelogs, runs configured post-version work, and consumes applied changesets.

Review the Git diff and run the repository's normal tests. Commit these generated files to the release branch, or let the generated GitHub Actions workflow maintain the release pull request.

6. Manually publish

After the version changes reach the branch used for publishing, provide the registry credentials required by the selected ecosystems.

Preview the publish run:

smif publish --dry-run

This validates package ordering and runs read-only registry pre-checks without publishing packages or creating Forge releases.

When the preview is correct:

smif publish

Packages publish in dependency order. The final report distinguishes successful, skipped, failed, and not-started packages. In CI, add --github-release when the configured GitHub Releases and assets should also be created.

If something fails

  • Package not found: use the PackageId key from [packages] in .changes/config.toml, not a guessed registry name.
  • Worktree is dirty: inspect and commit unrelated files first. --allow-dirty means you deliberately accept the current diff as input; it does not clean the repository.
  • Registry version already exists: Semifold skips that registry command. When GitHub Releases are enabled, it may still create a missing release; an existing release does not trigger asset recovery.
  • Publish partially fails: use the final successful, failed, and not-started states to repair the failing credential, pre-check, or command before retrying. Do not manually republish a version confirmed to exist.

Automation after the workflow is clear

Interactive prompts are the normal learning and local-maintenance path. CI systems and constrained environments can provide the same answers as flags:

smif init --resolvers rust \
  --base-branch main \
  --release-branch release \
  --default-tags \
  --github-actions

smif commit --name add-api \
  --package my-package=minor \
  --tag feat \
  --summary "Add the public API."

These flags are an automation compatibility surface, not a different release model.

You now have the complete basic lifecycle: discover packages, record a changeset, update related versions and changelogs, and publish in dependency order. Continue with the configuration overview when the repository needs more policy.

On this page