# How Worktrunk Manages Configuration Deprecation and Migration

> Learn how Worktrunk manages configuration deprecation with an idempotent migration engine. It transforms legacy TOML patterns in-memory, deduplicates warnings, and guides users to explicit updates.

- Repository: [Maximilian Roos/worktrunk](https://github.com/max-sixty/worktrunk)
- Tags: migration-guide
- Published: 2026-09-14

---

**Worktrunk treats configuration deprecation as a first-class concern through an idempotent migration engine in [`src/config/deprecation.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/deprecation.rs) that transforms legacy TOML patterns in-memory while deduplicating warnings and guiding users toward explicit updates.**

Worktrunk, an open-source command-line tool hosted at `max-sixty/worktrunk`, implements a sophisticated system to **manage configuration deprecation and migration** without breaking existing user setups. The deprecation framework ensures that outdated section names, renamed fields, and moved keys are automatically migrated during file loading while providing clear, actionable migration paths.

## The Deprecation Rules Engine

The core deprecation logic resides in **[`src/config/deprecation.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/deprecation.rs)**, which defines a `DEPRECATION_RULES` table containing every supported migration pattern. Each rule entry consists of two components: an **idempotent migration function** that rewrites outdated TOML into its modern equivalent, and a **warning generator** that constructs user-facing notifications about what changed.

This centralized approach allows Worktrunk to handle diverse migration scenarios—including renamed fields, moved keys, legacy template variables, and obsolete section names—through a unified interface. The rules are evaluated in a deterministic order during configuration loading to ensure predictable transformations.

## The Configuration Loading Pipeline

When Worktrunk loads a configuration file—whether user, system, or project-level—it invokes `deprecation::check_and_migrate` from the public API exported in [`src/config/mod.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/mod.rs). This function orchestrates a six-stage pipeline:

1. **Scan raw TOML content** against every rule in `DEPRECATION_RULES`, maintaining consistent ordering for warning emission.
2. **Apply migrations** via `compute_migrated_content` to produce a structurally valid TOML string representing the modern schema.
3. **Collect `DeprecationInfo`** detailing which rules fired, including original and migrated code snippets along with optional hints.
4. **Deduplicate warnings** per file path using the `WARNED_DEPRECATED_PATHS` set to prevent spamming identical messages during a single execution.
5. **Emit one-time hints** through `DEPRECATION_HINT_EMITTED` suggesting users run `wt config update` to materialize changes.
6. **Respect suppression** via `SUPPRESS_WARNINGS` for contexts like the picker or statusline where stderr output would disrupt the interface.

The migration is **purely in-memory**; no filesystem modifications occur during normal configuration loads.

```rust
// When loading a user config, the deprecation layer is invoked automatically.
let raw = std::fs::read_to_string(user_config_path)?;
let (migrated, info) = deprecation::check_and_migrate(
    raw,
    deprecation::ConfigFileKind::User,
    user_config_path,
)?;
// `migrated` is the TOML ready for deserialization.
// `info` contains any deprecation warnings to be printed.
if !info.warnings.is_empty() {
    eprintln!("{}", info.warnings);
}

```

## Persisting Migrations with `wt config update`

While the loading pipeline applies transformations in-memory, Worktrunk requires explicit user action to persist changes. The `wt config update` command (implemented in [`src/config/user/mod.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/user/mod.rs)) rewrites the configuration file with the migrated TOML content.

```bash

# Persist the migration (writes the updated config and copies approved commands):

wt config update

# Or preview the migrated file without overwriting:

wt config update --output -

```

For configurations containing approved commands that have moved to [`approvals.toml`](https://github.com/max-sixty/worktrunk/blob/main/approvals.toml), the system additionally invokes `copy_approved_commands_to_approvals_file` to migrate those entries to the appropriate destination.

Project-level configurations undergo the same deprecation pipeline in [`src/config/project.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/project.rs), ensuring consistency across user and project scopes.

## Context-Aware Warning Suppression

Worktrunk provides granular control over warning emission through the `SUPPRESS_WARNINGS` atomic flag. Commands that execute in contexts where stderr output would be undesirable—such as the interactive picker or statusline rendering—can call `suppress_warnings()` to silence deprecation notices for the remainder of the process lifetime.

```rust
// In a command that wants to hide deprecation warnings (e.g. the picker):
deprecation::suppress_warnings();   // silence further warnings for this process

```

This mechanism ensures that deprecation warnings appear during explicit configuration operations while remaining hidden during routine command execution.

## Unknown Field Detection

Parallel to the deprecation system, Worktrunk tracks **unknown fields** using a similar deduplication mechanism via `WARNED_UNKNOWN_PATHS`. The integration in [`src/config/unknown_tree.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/unknown_tree.rs) combines schema-level errors with deprecation warnings, providing a unified user experience for configuration issues. This allows the system to surface typos or obsolete keys that lack specific migration rules while preventing repetitive error messages.

## Summary

- **Centralized rules**: All deprecation logic lives in [`src/config/deprecation.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/deprecation.rs) within the `DEPRECATION_RULES` table.
- **Idempotent transformations**: Migration functions safely rewrite legacy TOML without side effects during the loading phase.
- **Deduplication**: The `WARNED_DEPRECATED_PATHS` set ensures users receive only one warning per deprecated pattern per file.
- **Explicit persistence**: Users must run `wt config update` to write migrated content, with optional preview via `--output`.
- **Contextual suppression**: The `SUPPRESS_WARNINGS` flag allows commands like the picker to disable stderr output when appropriate.
- **Unified error handling**: Unknown field detection integrates with deprecation warnings for comprehensive configuration validation.

## Frequently Asked Questions

### Where does Worktrunk define deprecation rules?

Worktrunk defines all deprecation patterns in **[`src/config/deprecation.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/config/deprecation.rs)** as entries in the `DEPRECATION_RULES` table. Each entry specifies an idempotent migration function and a warning generator, covering scenarios from renamed fields to moved configuration sections.

### How do I persist configuration migrations in Worktrunk?

Run the **`wt config update`** command to materialize in-memory migrations to disk. This command rewrites your configuration file with the updated TOML and handles auxiliary migrations like copying approved commands to [`approvals.toml`](https://github.com/max-sixty/worktrunk/blob/main/approvals.toml). Use the `--output -` flag to preview changes without writing to disk.

### Can deprecation warnings be disabled in Worktrunk?

Yes. For contexts where stderr output would be disruptive, such as the interactive picker or statusline, code can invoke **`deprecation::suppress_warnings()`** to disable warnings via the `SUPPRESS_WARNINGS` flag. This affects only the current process and is intended for programmatic contexts, not user preference.

### How does Worktrunk prevent duplicate deprecation warnings?

Worktrunk uses the **`WARNED_DEPRECATED_PATHS`** set to track which files have already triggered specific deprecation rules during the current execution. This deduplication ensures that loading a configuration file multiple times or referencing the same deprecated pattern does not flood the user with identical warning messages.