migrating-motoko
Inline actor migration for Motoko canisters using `(with migration = ...)` syntax. Use when upgrading canister state, renaming fields, changing field types, or restructuring actor state without the --enhanced-migration flag. For multi-step migration chains, use migrating-motoko-enhanced instead.
What this skill does
# Inline Actor Migration
Migrate actor state across canister upgrades using a migration expression attached to the actor. Each upgrade has at most one migration function.
**For multi-migration with a `migrations/` directory**, load `migrating-motoko-enhanced` instead.
## When to Use
### Implicit migration (no code needed)
The runtime allows the upgrade if the new program is compatible with the old:
- Adding actor fields
- Removing actor fields
- Changing mutability (`var` ↔ `let`)
- Adding variant constructors
- Widening types (`Nat` → `Int`)
### Explicit migration required
- Renaming fields
- Changing a field's type (e.g. `Bool` → variant, `Int` → `Float`)
- Restructuring state (splitting/merging fields)
- Transforming collection values
## Syntax
Parenthetical expression immediately before the actor:
```motoko
import Migration "migration";
(with migration = Migration.run)
actor {
var newState : Float = 0.0;
};
```
Or inline:
```motoko
import Int "mo:core/Int";
(with migration = func(old : { var state : Int }) : { var newState : Float } {
{ var newState = old.state.toFloat() }
})
actor {
var newState : Float = 0.0;
};
```
Or using the shorthand when the imported module exports a `migration` field:
```motoko
import { migration } "migration";
(with migration)
actor { ... };
```
## Migration Function Rules
- Type: `func (old : { ... }) : { ... }` — local, non-generic, both records must use persistable types (no functions or mutable arrays)
- **Domain**: old actor fields (names and types from the previous version)
- **Codomain**: new actor fields (must exist in the new actor with compatible types)
- Runs **only on upgrade** — on fresh install, initializers run normally
- If the migration traps, the upgrade is aborted and the canister stays on the old version
### Field semantics
| Field appears in | Effect |
| ---------------- | ------ |
| Input and output | Field is transformed |
| Output only | New field produced by migration |
| Input only | Field consumed (compiler warns about possible data loss) |
| Neither | Carried through or initialized by declaration |
## Migration Module Pattern
Keep migrations in a separate module. Define old types inline — do not import them from old code paths:
```motoko
// migration.mo
import Types "types";
import Map "mo:core/Map";
module {
type OldTask = { id : Nat; title : Text; completed : Bool };
type OldActor = {
var tasks : Map.Map<Nat, OldTask>;
var nextId : Nat;
};
type NewActor = {
var tasks : Map.Map<Nat, Types.Task>;
var nextId : Nat;
};
public func run(old : OldActor) : NewActor {
let tasks = old.tasks.map<Nat, OldTask, Types.Task>(
func(_, task) {
{
id = task.id;
title = task.title;
due = 0;
var status = if (task.completed) #completed else #pending;
}
}
);
{ var tasks; var nextId = old.nextId };
};
};
```
```motoko
// main.mo
import Map "mo:core/Map";
import Types "types";
import Migration "migration";
(with migration = Migration.run)
actor {
var tasks = Map.empty<Nat, Types.Task>();
var nextId : Nat = 0;
};
```
Fields must have initializers — the migration function runs only on **upgrade**. On fresh install the initializers are used.
## Common Patterns
### Add field with default
```motoko
old.users.map<Nat, OldUser, NewUser>(
func(_, u) { { u with zipCode = "" } }
)
```
### Add optional field
```motoko
{ task with var assignee = null : ?Principal }
```
### Bool to variant
```motoko
var status = if (task.completed) #completed else #pending;
```
### Rename a field
Consume old name, produce new name:
```motoko
func(old : { var state : Int }) : { var value : Int } {
{ var value = old.state }
}
```
### Drop a field
Consume it in the input, omit from output. Compiler warns — ensure the loss is intentional.
## Checklist
- [ ] Decide: implicit (compatible change) or explicit (migration function)
- [ ] If explicit: define old types inline in `migration.mo`
- [ ] Migration type: `func (old : RecordIn) : RecordOut` with persistable types
- [ ] Attach with `(with migration = Migration.run)` before the actor
- [ ] Do not use `preupgrade`/`postupgrade` for data migration
- [ ] Verify with `mops check --fix` and `mops build`
## Additional References
- Load `motoko` for general Motoko language reference and mo:core APIs
- Load `migrating-motoko-enhanced` for multi-migration with `--enhanced-migration`
- Load `mops-cli` for `mops check`, `mops build`, and toolchain setup
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.