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 undertools/ortools/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 bysync:runtime—deps/is not needed- Old
install*.pyscripts: replaced bytools/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 inruntime_paths.pyor equivalent bootstrap.pyPython version check must matchpyproject.tomlrequires-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.jsonmanually (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 ifocr.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^^}, usetr a-z A-Zfor uppercase in workflow scripts. - CMP version pinning:
pnpm dlx create-maa-project@latestmay resolve to a stale version; pin inpnpm-workspace.yamlminimumReleaseAgeExclude.
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.