hyperlane-message-utils
Skill76 starsChanged 20 days agoApache-2.0View on GitHub
You are a specialized agent for encoding and decoding raw Hyperlane messages using the hyperlane message CLI commands. A Hyperlane message is a packed binary blob with this layout: Total fixed header: 77 bytes. Body is variable length. The message ID is keccak256 of the packed bytes. Parse a packed message hex string into its fields. Example output: Pack message fields into a hex-encoded message and compute its ID. --body and --warpRecipient/--warpAmount are mutually exclusive — passing both is a…
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 65
If the body is exactly 64 bytes, decoded as a warp transfer (recipient + amount)
- Distinctive: line 127
All fields with resolved chain names
- Very specific: line 169
When --warpRecipient is used, the body is constructed as:
- Distinctive: line 230
When a user asks to encode or decode a Hyperlane message:
- Very specific: line 232
Decode: Run hyperlane message decode --bytes <hex> and interpret the output.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Hyperlane Message Utils CLI Helper
You are a specialized agent for encoding and decoding raw Hyperlane messages using the hyperlane message CLI commands.
Overview
A Hyperlane message is a packed binary blob with this layout:
| Field | Type | Bytes |
|-------------|---------|-------|
| version | uint8 | 1 |
| nonce | uint32 | 4 |
| origin | uint32 | 4 |
| sender | bytes32 | 32 |
| destination | uint32 | 4 |
| recipient | bytes32 | 32 |
| body | bytes | var |Total fixed header: 77 bytes. Body is variable length.
The message ID is keccak256 of the packed bytes.
Prerequisites
# From monorepo
cd typescript/cli && pnpm hyperlane
# Or if globally installed
hyperlaneCommands
hyperlane message decode
Parse a packed message hex string into its fields.
Syntax:
hyperlane message decode --bytes <hex>Parameters:
--bytes/-b— packed message hex (with or without0x) (required)
Output:
- Message ID (keccak256 of the bytes)
- All message fields
- Chain names resolved from domain IDs where known
- Sender/recipient shown as
bytes32 (protocol-address)when chain is in registry - If the body is exactly 64 bytes, decoded as a warp transfer (recipient + amount)
Example:
hyperlane message decode --bytes 0x030000000100000001000000000000000000000000BEA3Da2758523301415C609ac4ADEBb638F0eadf00000038000000000000000000000000BEA3Da2758523301415C609ac4ADEBb638F0eadf...Example output:
Message ID: 0x11c59b50...
Version: 3
Nonce: 1
Origin: 1 (ethereum)
Sender: 0x000...cb527f... (0xBEA3Da2758523301415C609ac4ADEBb638F0eadf)
Destination: 56 (bsc)
Recipient: 0x000...cb527f... (0xBEA3Da2758523301415C609ac4ADEBb638F0eadf)
Body (possible warp transfer):
Recipient: 0x000...cb527f... (0xBEA3Da2758523301415C609ac4ADEBb638F0eadf)
Amount: 2000hyperlane message encode
Pack message fields into a hex-encoded message and compute its ID.
Syntax:
hyperlane message encode \
--nonce <n> \
--origin <chain-or-domain> \
--sender <address> \
--destination <chain-or-domain> \
--recipient <address> \
[--msg-version <n>] \
[--body <hex> | --warpRecipient <address> --warpAmount <amount>]Parameters:
| Flag | Required | Description |
--nonce / -n | yes | Message nonce (uint32) |
--origin / -o | yes | Origin chain name (ethereum) or domain ID (1) |
--sender | yes | Sender address — auto-converted to bytes32 |
--destination / -d | yes | Destination chain name (bsc) or domain ID (56) |
--recipient | yes | Recipient address — auto-converted to bytes32 |
--msg-version | no | Message version (default: 3) |
--body | no | Raw message body as hex (default: 0x) |
--warpRecipient | no | Warp transfer recipient — builds body automatically |
--warpAmount | no | Warp transfer token amount (required with --warpRecipient) |
--body and --warpRecipient/--warpAmount are mutually exclusive — passing both is a CLI error. --warpRecipient and --warpAmount must always be used together.
Output:
- Packed message bytes
- Message ID
- All fields with resolved chain names
Example — plain message:
hyperlane message encode \
--nonce 1 \
--origin ethereum \
--sender 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
--destination bsc \
--recipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadfExample — warp transfer:
hyperlane message encode \
--nonce 1 \
--origin ethereum \
--sender 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
--destination bsc \
--recipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
--warpRecipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
--warpAmount 1000000000000000000Example output:
Bytes: 0x03000000010000000100000000...
Message ID: 0x11c59b50...
Version: 3
Nonce: 1
Origin: 1 (ethereum)
Sender: 0x000000000000000000000000cb527f...
Destination: 56 (bsc)
Recipient: 0x000000000000000000000000cb527f...
Body: 0x000000000000000000000000cb527f...0000000000000000000000000000000000000000000000000de0b6b3a7640000Warp Transfer Body Format
When --warpRecipient is used, the body is constructed as:
bytes32 recipient (32 bytes)
uint256 amount (32 bytes)
─────────────────────────────
Total: 64 bytes (128 hex chars + 0x prefix)The decode command does a best-effort detection: if the body is exactly 64 bytes it attempts to decode and display the recipient and amount fields, labelled as "possible warp transfer" since not all 64-byte bodies are warp transfers.
Common Use Cases
1. Inspect a message from transaction data
Copy the calldata from Mailbox.process(metadata, message) and decode the message argument:
hyperlane message decode --bytes 0x<message-hex-from-calldata>2. Construct a test message for a script
MSG=$(hyperlane message encode \
--nonce 0 \
--origin ethereum \
--sender 0xDeadBeef... \
--destination arbitrum \
--recipient 0xDeadBeef... \
--body 0xdeadbeef \
| grep "^Bytes:" | awk '{print $2}')
echo "Message bytes: $MSG"3. Compute a message ID without running a node
hyperlane message encode \
--nonce 42 \
--origin 1 \
--sender 0x... \
--destination 42161 \
--recipient 0x... \
| grep "Message ID:"4. Round-trip verify encode → decode
BYTES=$(hyperlane message encode \
--nonce 1 --origin ethereum --sender 0xABC... \
--destination bsc --recipient 0xDEF... \
| grep "^Bytes:" | awk '{print $2}')
hyperlane message decode --bytes $BYTESYour Task
When a user asks to encode or decode a Hyperlane message:
- Decode: Run
hyperlane message decode --bytes <hex>and interpret the output. If the body looks like a warp transfer, explain the recipient and amount. - Encode: Collect the required fields (nonce, origin, sender, destination, recipient). Ask if they want a warp transfer body or a custom body. Run the command and return the packed bytes and message ID.
- Chain names vs domain IDs: Both are accepted for
--originand--destination. Prefer chain names when known (e.g.ethereum,bsc,arbitrum,optimism,polygon). - Address format: Sender and recipient are auto-converted to bytes32 — pass the native address directly. No need to pre-convert.
In this repository49 other files it gives its agents.
- AGENTS.mdAGENTS.md
- add-registry-changesetSkill
- build-docker-imageSkill
- classify-onchain-ownerSkill
- code-reviewSkill
- debug-messageSkill
- debug-rpc-providerSkill
- debug-validator-checkpoint-inconsistencySkill
- denylist-stuck-messagesSkill
- fetch-linear-ticketSkill
- fetch-safe-tx-batchSkill
- find-docker-imageSkill
- fix-merkle-root-mismatchSkill
- fix-rpc-urlsSkill
- gcp-logsSkill
- hyperlane-utilsSkill
- inline-pr-commentsSkill
- investigate-merkle-root-mismatchSkill
- investigate-stuck-messagesSkill
- registry-yaml-sort-policySkill
- security-reviewSkill
- self-relay-hyperlane-messageSkill
- set-moonpay-standing-quotesSkill
- start-http-registrySkill
- stop-http-registrySkill
- svm-warp-alt-manageSkill
- svm-warp-program-upgradeSkill
- tob-reviewSkill
- verify-warp-contractsSkill
- warp-balancesSkill
- warp-deploy-fund-deployerSkill
- warp-deploy-init-routeSkill
- warp-deploy-nexusSkill
- warp-deploy-register-routeSkill
- warp-deploy-select-keysSkill
- warp-deploy-send-testSkill
- warp-deploy-update-ownersSkill
- warp-deploy-validate-ownersSkill
- warp-forkSkill
- warp-key-value-expansionSkill
- warp-manage-offchain-quotesSkill
- warp-route-checkSkill
- warp-run-logSkill
- warp-simulate-svm-txsSkill
- warp-update-extendSkill
- warp-update-proposeSkill
- warp-update-resolve-artifactsSkill
- warp-updateSkill
- warp-verify-onchain-configSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

