Distilly Legacy Skill Compatibility: Handling Historic Skill Structures

Distilly maintains backward compatibility with legacy "colleague"-centric skill layouts through a layered approach that mirrors legacy fields, resolves both new and historic storage roots, and automatically generates compatibility metadata.

The titanwings/distilly repository implements a robust Distilly legacy skill compatibility system that allows modern skill definitions to coexist with historic directory structures and metadata formats. This architecture ensures that existing tooling, backup scripts, and CLI workflows continue to function without requiring manual migration of legacy assets.

Legacy-to-Canonical Field Mapping

The core compatibility shim resides in tools/skill_schema.py, where the sync_legacy_fields() function (lines 208–233) preserves backward compatibility by copying new schema values back into top-level legacy keys. This method ensures that fields like legacy_command, legacy_storage_root, and legacy_type remain populated even as the canonical schema evolves.

When processing skill metadata, Distilly automatically invokes this synchronization to maintain the original "colleague"-centric field structure that legacy tooling expects.

Automatic Compatibility Metadata Injection

After enriching a skill's metadata, the enrich_skill_meta() function injects a compat dictionary containing legacy identifiers (lines 222–226). This compatibility block is subsequently written to meta.json by the writer module.

The injection occurs automatically during the enrichment pipeline, ensuring that every skill—whether created through modern or legacy workflows—carries the necessary metadata for backward compatibility.

Preset-Based Legacy Value Management

Each character preset in tools/skill_presets.py declares specific legacy values that feed into the compatibility system:

  • Colleague preset (lines 34–50): Uses legacy alias /create-colleague, storage root colleagues, and type colleague
  • Relationship preset (lines 61–77): Uses legacy alias /create-ex, storage root skills/relationship, and type relationship
  • Celebrity preset (lines 84–90): Uses legacy alias /create-icon, storage root skills/celebrity, and type celebrity

These preset definitions allow Distilly to automatically populate the compatibility block with the correct legacy identifiers based on the selected character type.

Resolving Historic Storage Paths

The resolve_existing_storage_root() function (lines 71–88) implements intelligent path resolution that bridges old and new directory structures. When locating an existing skill, the function first checks the canonical storage root; if the slug is not present there, it falls back to the legacy root path.

This transparent resolution enables the engine to address skills in both new canonical locations and historic "colleague" directories without requiring user configuration changes.

Version Management and Layout Preservation

The version manager in tools/version_manager.py (lines 5–7) explicitly maintains the legacy colleague layout during archive and restore operations. This ensures that older backup scripts and version control workflows continue to operate correctly, even as the underlying storage schema evolves.

Metadata Persistence

When writing artifacts, tools/skill_writer.py (lines 64–66) calls sync_legacy_fields() again during the meta.json serialization process. This double-synchronization ensures that the output file always contains the legacy keys required by external tooling, regardless of when the skill was originally created.

Practical Implementation Examples

The following examples demonstrate how to work with legacy compatibility features in Distilly:


# Enrich a raw legacy dict and obtain a compatibility block

from tools.skill_schema import enrich_skill_meta

legacy_meta = {
    "name": "Old Colleague",
    "character": "colleague",               # legacy field

    "tags": ["team", "project"],            # legacy tags style

}
slug = "old-colleague"
full_meta = enrich_skill_meta(legacy_meta, slug)
print(full_meta["compat"])

# {'legacy_command': '/create-colleague',

#  'legacy_storage_root': 'colleagues',

#  'legacy_type': 'colleague', ...}

# Resolve a storage root that may be legacy or canonical

from tools.skill_presets import resolve_existing_storage_root

# Assume a skill lives under the old "colleagues/old-colleague" path

root = resolve_existing_storage_root("colleague", slug="old-colleague")
print(root)  # -> Path('colleagues') if legacy exists, else Path('skills/colleague')

# CLI: Create a skill using a legacy-compatible command alias

distilly.mjs --action create \
  --slug old-colleague \
  --name "Old Colleague" \
  --character colleague \
  --work work.md \
  --persona persona.md

# The generated meta.json will contain the `compat` block automatically.

Summary

  • Field Mirroring: sync_legacy_fields() in tools/skill_schema.py (lines 208–233) copies modern schema values into legacy keys like legacy_command and legacy_storage_root.
  • Metadata Injection: The enrich_skill_meta() function automatically populates a compat dictionary (lines 222–226) that preserves legacy identifiers within meta.json.
  • Preset Definitions: tools/skill_presets.py (lines 34–90) defines legacy aliases and storage roots for colleague, relationship, and celebrity character types.
  • Path Resolution: resolve_existing_storage_root() (lines 71–88) implements fallback logic that checks canonical paths before defaulting to legacy directory structures.
  • Layout Preservation: The version manager maintains legacy colleague layouts during archival, while the skill writer ensures legacy fields persist in serialized metadata.

Frequently Asked Questions

How does Distilly handle storage path resolution for legacy skills?

When locating an existing skill, the resolve_existing_storage_root() function in tools/skill_presets.py first validates the canonical storage root. If the skill slug is absent from that location, the system automatically falls back to the legacy root directory defined by the character preset. This enables transparent access to both new and historic directory structures without requiring manual path configuration.

What specific legacy fields does Distilly preserve in skill metadata?

According to the source code in tools/skill_schema.py, Distilly preserves three critical legacy fields: legacy_command, legacy_storage_root, and legacy_type. These values are populated by sync_legacy_fields() and stored within a dedicated compat dictionary inside meta.json, ensuring that external tooling expecting the original "colleague"-centric schema remains functional.

Which character types support legacy compatibility aliases?

The tools/skill_presets.py file defines legacy compatibility for three distinct character presets. The colleague preset uses the /create-colleague alias, the relationship preset uses /create-ex, and the celebrity preset uses /create-icon. Each preset declares its specific legacy storage root and type identifier, enabling the framework to automatically generate appropriate compatibility metadata based on the selected character type.

Does Distilly require manual migration of existing legacy skills?

No manual migration is necessary. Distilly automatically detects and handles legacy skills through the fallback path resolution implemented in resolve_existing_storage_root(). Additionally, the enrich_skill_meta() function automatically generates compatibility metadata for existing assets, while the version manager preserves legacy layouts during backup and restore operations. This architecture ensures seamless interoperability between historic and modern skill definitions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →