# Maafw Template Migration

> Migrate a legacy MaaFramework project to the create-maa-project scaffold. Use when moving an old MAA-style project with assets/ + deps/ structure and install_*.py CI scripts to the CMP template (maa-project.json, build-release.mjs, sync-runtime.mjs).

- Skill: `maaxyz/maafw-template-migration` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add maaxyz/maafw-template-migration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/maaxyz/maafw-template-migration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: maaxyz (https://skillmd.com/u/maaxyz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/maaxyz/maafw-template-migration

---


# MaaFramework Project Template Migration

Guide for migrating legacy MaaFW projects to the create-maa-project (CMP) scaffold.

## When to use

- Old project has `assets/` (resource + interface.json), `deps/` (MaaFramework binaries), `install*.py` (packaging scripts, possibly under `tools/` or `tools/ci/`)
- Moving to CMP's `maa-project.json` + `tools/build-release.mjs` + `tools/sync-runtime.mjs`

## Migration workflow

### 1. Scaffold a fresh CMP project

In a new directory, run CMP to generate a clean project skeleton:

```bash
pnpm dlx create-maa-project@latest
```

Select template (agent or pipeline-only), GUI types, OCR source, etc. This generates `maa-project.json`, `interface.json`, `tools/build-release.mjs`, `tools/sync-runtime.mjs`, `.github/workflows/release.yml`, `package.json`, `.gitignore`, and other boilerplate. Keep these generated files as the base — do not overwrite them with old project files.

### 2. Migrate old content into the scaffolded structure

Bring over only project-specific content from the old project:

| Old | New | Notes |
|---|---|---|
| `assets/resource/` | `resource/base/` | Drop `assets/`, rename `resource` to `base` |
| `assets/resource_bilibili/` | `resource/bilibili/` | Same pattern for each variant |
| `assets/interface.json` | `interface.json` (root) | Overwrite the CMP-generated one, but keep the `version` field CMP added |
| `tasks/` | `tasks/` | Usually direct copy |
| Old agent code | `agent/` | If using agent template; update hardcoded paths |

### 3. Configure maa-project.json

Fill in project-specific settings: GUI types and channels, resource packs, controllers, OCR source, Python version. CMP generates a template but it needs real values.

### 4. Extract non-MaaFW-bundle content from resource

Old projects often keep everything under `resource/` — images, pipeline JSON, AND hot-update data. In the new structure, anything that is not part of the MaaFW bundle (images, models, pipeline) should be pulled out of `resource/`. For example, if old `resource/data/` contains hot-update data, it moves to top-level `data/`. Whether this data involves manifest caching depends on the project — CMP does not assume either way.

### 5. Clean up obsolete paths

- `deps/` directory: MaaFramework runtime binaries are now downloaded by `sync:runtime` — `deps/` is not needed
- Old `install*.py` scripts: replaced by `tools/build-release.mjs`
- `assets/` wrapper: gone, content moved to root-level directories

## OCR models

If using MaaCommonAssets submodule for OCR, `resource/base/model/ocr/` is generated by `sync:runtime` and should be gitignored. If managing OCR models manually (committed files), do not gitignore.

## Agent code path updates

If the project has a Python agent, check for hardcoded paths after migration:

- Any `assets/` references in agent code need updating to new layout
- If data moved out of `resource/`, update paths in `runtime_paths.py` or equivalent
- `bootstrap.py` Python version check must match `pyproject.toml` `requires-python`

## interface.json

- Keep the `"version"` field (CMP adds it, build-release requires it)
- CMP does not manage this file — controller/resource entries must match `maa-project.json` manually (lint warns but allows drift)

## Common pitfalls

1. **ocr.files key order**: CMP expects `{"destName": "srcRel"}` (destination filename to source path within submodule). Inverted = ENOENT on sync. Only relevant if `ocr.source = "submodule"`.
2. **logo.ico not in git**: if the release workflow checks `hashFiles('logo.ico')`, the ico file must be committed — a generated or gitignored ico will cause the icon step to be silently skipped.
3. **macOS bash 3.2**: GitHub macOS runners use bash 3.2 — no `${var^^}`, use `tr a-z A-Z` for uppercase in workflow scripts.
4. **CMP version pinning**: `pnpm dlx create-maa-project@latest` may resolve to a stale version; pin in `pnpm-workspace.yaml` `minimumReleaseAgeExclude`.

## Backporting to create-maa-project

Generic fixes discovered during migration should be backported to CMP templates. Project-specific logic (private module downloads, specific mirrorchyan_rid values, manifest cache generation) stays in the project repo.

