| name | maafw-template-migration |
| description | 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). |
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:
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
- 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".
- 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.
- macOS bash 3.2: GitHub macOS runners use bash 3.2 — no
${var^^}, use tr a-z A-Z for uppercase in workflow scripts.
- 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.