Agent skill · software engineering · caffeinelabs

writing-motoko

Motoko language reference, architecture patterns, and dependency tooling (mops). Load when writing or modifying backend .mo files.

Why this skill is useful

Provides specific architectural patterns and dependency management practices for the Motoko language that the AI wouldn't reliably generate on its own.

What it needs

Requires mops installed locally. About 12k tokens when loaded. Last updated 2026-08-06.

What this skill does

Writing Motoko Motoko is an under-represented language for the Internet Computer Protocol, so your pre-training data is likely to be outdated — always favour this skill and its documentation for the most up-to-date information. Critical Requirements NEVER use these: stable keyword -- Not needed in enhanced orthogonal persistence mode mo:base library -- Deprecated. Use mo:core instead .vals() -- The deprecated mo:base iterator name. Always .values(). On arrays .vals() still compiles, so nothing flags it; on core collections it fails with M0072 system func preupgrade/postupgrade -- Not needed with enhanced orthogonal persistence (with migration = ...) actor-attached migration syntax -- Use the mops-managed migration chain in migrations/ Inline initializers on stable actor fields -- Initial values come from the migration chain (see migrating-motoko-actors) Module function style for self parameters -- Don't write List.add(list, item) or Map.get(map, key) Manual field-by-field record copying for immutable records -- Use record spread ({ self with ... }). For records with var fields, do not use record spread; mutate the var field directly or rebuild the record explicitly. Single-file monolithic actors -- Use the multi-file architecture: types.mo, lib/, mixins/, main.mo Stable state in a mixin block -- a bare let/var is silently stable and traps at runtime (IC0503). Pass state in as a parameter and keep constants in a module Any Motoko reserved keyword as a declared identifier -- Before writing, check parameter, variable, function, type, field, and label names against the full list in references/reserved-keywords.md. query and label are reserved and must never be identifiers. Rename a colliding domain term instead of relying on its position or inferred meaning. Type annotations on an inline func passed as a call argument -- write xs.filter(func x = x > 1), not xs.filter(func(x : Nat) : Bool { x > 1 }). The call supplies the types. …

How to use it

Reference it in AdaL, Claude Code, Cursor or any coding agent — nothing to install:

@skills caffeinelabs/writing-motoko

View the source on GitHub

Browse the @skills marketplace