# How Claude HUD Handles Config Migration for Legacy Upgrades

> Learn how Claude HUD automatically migrates legacy config formats by converting obsolete layout properties to the current HudConfig schema during initialization.

- Repository: [Jarrod Watts/claude-hud](https://github.com/jarrodwatts/claude-hud)
- Tags: migration-guide
- Published: 2026-03-18

---

**Claude HUD automatically migrates legacy configuration formats by detecting obsolete `layout` properties in [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json) and transforming them into the current `HudConfig` schema during the initialization process.**

The `jarrodwatts/claude-hud` repository maintains backward compatibility through a robust migration system that ensures user preferences persist across schema changes. When the plugin initializes, it reads the user's [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json) file and seamlessly upgrades outdated structures without manual intervention. This Claude HUD config migration process handles both string-based and object-based legacy layouts while preserving valid modern settings.

## Understanding the Configuration Schema Evolution

Early versions of Claude HUD stored display preferences in a single `layout` property within [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json). This legacy field accepted either string values like `"separators"` or complex objects written by third-party tools.

Modern releases use a structured **HudConfig** interface defined in [`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts). This schema separates concerns into distinct properties including `lineLayout`, `showSeparators`, and `pathLevels`, providing granular control over the heads-up display appearance.

The migration bridge between these formats occurs within the `mergeConfig` function, which delegates legacy transformation to `migrateConfig` before applying defaults and validation.

## The Migration Pipeline: From Load to Validation

When `loadConfig` reads the user's configuration file, it immediately passes the parsed object through `mergeConfig`. This function orchestrates a four-step **Claude HUD config migration** workflow:

### Step 1: Detecting Legacy Layout Formats

The `migrateConfig` function (lines 182–206 in [`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts)) first checks for the presence of a `layout` property in the loaded configuration. If found, the function determines whether the legacy field contains a string primitive or a complex object, applying different transformation logic for each type.

### Step 2: Transforming String-Based Layouts

If the legacy `layout` property is a string, the migration maps specific values to new boolean and enum fields:

- When `layout` equals `"separators"`, the migration sets `lineLayout: "compact"` and `showSeparators: true`
- For any other string value, it assigns `lineLayout: "compact"` and `showSeparators: false`

This logic occupies lines 185–194 in [`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts).

### Step 3: Handling Object-Based Legacy Layouts

Third-party tools or advanced users may have written `layout` as an object containing nested configuration. When `migrateConfig` detects an object type (lines 195–200), it extracts any existing `lineLayout`, `showSeparators`, and `pathLevels` properties from within that object and hoists them to the top-level configuration structure.

### Step 4: Cleanup and Default Merging

After extracting values, the migration explicitly deletes the obsolete `layout` key at line 202 to prevent confusion. The resulting partial configuration then merges with `DEFAULT_CONFIG` (lines 218–235), filling any missing properties with sensible defaults. Validation helpers like `validateLineLayout` and `validatePathLevels` ensure the final `HudConfig` object conforms to expected types before the plugin uses it.

## Implementation Details in src/config.ts

The core migration logic resides in [`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts), which also defines the default configuration constants and type guards. The `loadConfig` function in this file determines the configuration directory via [`src/claude-config-dir.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/claude-config-dir.ts), reads the JSON file, and triggers the migration chain.

Key functions involved in the process:

- **`migrateConfig`** – Detects and transforms legacy `layout` fields into modern properties
- **`mergeConfig`** – Orchestrates migration, validation, and default value application
- **`validateLineLayout`** – Ensures migrated layout values match allowed enum variants
- **`validatePathLevels`** – Confirms numeric path depth settings are within acceptable ranges

## Practical Examples

The following pattern demonstrates automatic migration during initialization:

```typescript
import { loadConfig } from './config.js';

async function initHud() {
  const cfg = await loadConfig();   // ← migration happens inside
  console.log('Effective config:', cfg);
}
initHud();

```

For debugging or manual upgrade scenarios, you can invoke the merger directly:

```typescript
import { mergeConfig } from './config.js';

// Example of an old config file
const oldConfig = {
  layout: 'separators',          // legacy string
  // other future‑proof fields may be present
};

const newConfig = mergeConfig(oldConfig);
console.log(newConfig.lineLayout);      // "compact"
console.log(newConfig.showSeparators);  // true

```

## Summary

- **Claude HUD config migration** occurs automatically when `loadConfig` parses [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json), requiring no user intervention.
- The system handles both string-based legacy layouts (converting `"separators"` to boolean flags) and object-based layouts (extracting nested properties).
- After migration, the obsolete `layout` field is deleted to prevent schema conflicts.
- Validation functions ensure migrated values conform to the current `HudConfig` interface before merging with defaults.
- All logic is centralized in [`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts), with configuration paths resolved via [`src/claude-config-dir.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/claude-config-dir.ts).

## Frequently Asked Questions

### What triggers config migration in Claude HUD?

Migration triggers automatically during the `loadConfig` execution whenever the system detects a `layout` property in the user's [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json). This occurs every time the plugin initializes, ensuring legacy files are upgraded transparently before the HUD renders.

### What happens if my legacy config uses a custom layout object?

If your existing configuration stores `layout` as an object rather than a string, the `migrateConfig` function extracts any valid `lineLayout`, `showSeparators`, or `pathLevels` properties from within that object. These values are promoted to top-level fields, and the original nested structure is discarded after extraction.

### Is the original config.json file modified during migration?

The migration process transforms the configuration in memory during the merge phase. While the raw file on disk remains unchanged during reading, Claude HUD typically writes the validated and merged configuration back to [`config.json`](https://github.com/jarrodwatts/claude-hud/blob/main/config.json), effectively persisting the modernized schema for future launches.

### Which validation functions ensure migrated configs are valid?

After migration, `mergeConfig` invokes `validateLineLayout` to confirm the layout string matches allowed values like `"compact"` or `"expanded"`, and `validatePathLevels` to verify numeric settings are valid. These guards prevent malformed legacy data from crashing the plugin.