feat(skills): add controller-integration skill for mobile and extension#62
Merged
NicolasMassart merged 2 commits intoJul 7, 2026
Merged
Conversation
Adds the verified metamask-extension repo overlay for the controller-integration skill and generalizes the base skill description to cover both mobile Engine and extension background integration paths. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
Adds a new controller-integration skill under domains/coding/skills/ to guide integrating controllers into MetaMask Mobile (Engine) and MetaMask Extension (background messenger-client init), with repo-specific overlays.
Changes:
- Adds the base
controller-integrationskill definition (skill.md). - Adds a MetaMask Mobile overlay documenting the Engine controller integration workflow and verification steps.
- Adds a MetaMask Extension overlay documenting background messenger-client init integration steps, including state/persistence and safety checks.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| domains/coding/skills/controller-integration/skill.md | Defines the new skill and when to use it. |
| domains/coding/skills/controller-integration/repos/metamask-mobile.md | Mobile-specific controller integration steps for Engine (messengers, init, state, verification). |
| domains/coding/skills/controller-integration/repos/metamask-extension.md | Extension-specific background integration steps for messenger-client init (init map, state flattening, filtering, verification). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds the
controller-integrationskill: a baseskill.mdplus repo overlays for MetaMask Mobile (Engine) and MetaMask Extension (background messenger-client init), based on verified read-only exploration of both codebases.Fixes https://consensyssoftware.atlassian.net/browse/MCWP-471
Type of Change
Skill Details (if adding a new skill)
Provider Name: MetaMask
Skill Name: controller-integration
Brief Description: Wire a new or existing controller into the MetaMask Mobile Engine or the MetaMask Extension background — init function, messenger, delegation, state persistence, feature gating, and verification steps for each repo.
Checklist
Testing
metamask-skills.mjs describe coding/controller-integration --repo metamask-extension→repo match: yesmetamask-skills.mjs describe coding/controller-integration --repo metamask-mobile→repo match: yesnode --test test/*.test.mjs→ 36/36 passAdditional Context
Example of agent chat using the skill
Mobile (Sonnet 4.6 medium)
I want to implement a controller, how should I do?
Here is the full process to integrate a controller into the MetaMask Mobile Engine.
Path decision
First, determine which path applies to your controller:
AccountsController,KeyringController,NetworkController, etc. — usethis.#wallet.getInstance('<Name>')Then, decide the source of the class:
yarn add @metamask/<name>-controllerapp/core/Engine/controllers/<name>-controller/with a class,types.ts, and default stateCanonical examples to copy from
config-registry-controller-init.ts+ its messenger — standard npm-package patterncard-controller/— repo-local patternmoney-account-upgrade-controller-init.ts— cross-controller delegation and remote-flag gatingrewards-controller/— repo-local + remote-flag gatingSteps (in order)
yarn add) or create the local controller folderapp/core/Engine/messengers/<name>-controller-messenger.ts— usegetXControllerMessengerwithmessenger.delegate(...)for every allowed action/eventexpect(messenger).toBeInstanceOf(Messenger)MESSENGER_FACTORIESinapp/core/Engine/messengers/index.tsapp/core/Engine/types.ts— add toGlobalActions,GlobalEvents,MessengerClients,EngineState,MessengerClientsToInitializeMessengerClientInitFunctionreturning{ controller }buildMessengerClientInitRequestMockBACKGROUND_STATE_CHANGE_EVENT_NAMESinconstants.ts(:stateChangeor:stateChanged)Engine.ts— import init fn, add toinitFunctionsafter its dependencies, add tothis.context, add toget state()app/util/test/initial-background-state.jsonwith the default stateapp/selectors/<name>.ts—state.engine.backgroundState.<Name> ?? getDefault<Name>State().github/CODEOWNERStests/feature-flags/feature-flag-registry.tsVerify your wiring
yarn jest app/core/Engine/Engine.test.ts -t 'matches initial state fixture' yarn tsc --noEmit -p tsconfig.jsonCommon silent failures (no type error)
BACKGROUND_STATE_CHANGE_EVENT_NAMES→ Redux state goes stale after init:stateChangevs:stateChanged) → same symptomget state()→ Redux getsundefinedfor that key@metamask/messengerExtension (Sonnet 4.6 medium)
I want to implement a controller, how should I do?
Here's a summary of the key steps to implement a controller in this codebase:
1. File structure
Create a folder under
app/scripts/controllers/your-controller/:your-controller.ts— main controller fileyour-controller.test.ts— colocated teststypes.ts— TypeScript types and messenger types2. Define types and messenger
3. Define metadata and default state
4. Implement the controller class
5. Export selectors (not getters)
Key rules to remember
this.update()only, never direct mutationgetDefault...State()function, not objectOnce you're done, if you also need to wire the controller into the extension, let me know and I can guide you through the integration step (connecting it to
metamask-controller.ts, the messenger client, and Redux).