agentleFS
hyperlane-xyzhyperlane-xyz/hyperlane-monorepo/.agents/skills/hyperlane-message-utils/SKILL.md

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
  1. Distinctive:

    If the body is exactly 64 bytes, decoded as a warp transfer (recipient + amount)

    line 65
  2. Distinctive:

    All fields with resolved chain names

    line 127
  3. Very specific:

    When --warpRecipient is used, the body is constructed as:

    line 169
  4. Distinctive:

    When a user asks to encode or decode a Hyperlane message:

    line 230
  5. Very specific:

    Decode: Run hyperlane message decode --bytes <hex> and interpret the output.

    line 232

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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
hyperlane

Commands

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 without 0x) (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:    2000

hyperlane 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:

FlagRequiredDescription
--nonce / -nyesMessage nonce (uint32)
--origin / -oyesOrigin chain name (ethereum) or domain ID (1)
--senderyesSender address — auto-converted to bytes32
--destination / -dyesDestination chain name (bsc) or domain ID (56)
--recipientyesRecipient address — auto-converted to bytes32
--msg-versionnoMessage version (default: 3)
--bodynoRaw message body as hex (default: 0x)
--warpRecipientnoWarp transfer recipient — builds body automatically
--warpAmountnoWarp 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 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf

Example — warp transfer:

hyperlane message encode \
  --nonce 1 \
  --origin ethereum \
  --sender 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
  --destination bsc \
  --recipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
  --warpRecipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
  --warpAmount 1000000000000000000

Example output:

Bytes:       0x03000000010000000100000000...
Message ID:  0x11c59b50...
Version:     3
Nonce:       1
Origin:      1 (ethereum)
Sender:      0x000000000000000000000000cb527f...
Destination: 56 (bsc)
Recipient:   0x000000000000000000000000cb527f...
Body:        0x000000000000000000000000cb527f...0000000000000000000000000000000000000000000000000de0b6b3a7640000

Warp 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 $BYTES

Your Task

When a user asks to encode or decode a Hyperlane message:

  1. Decode: Run hyperlane message decode --bytes <hex> and interpret the output. If the body looks like a warp transfer, explain the recipient and amount.
  2. 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.
  3. Chain names vs domain IDs: Both are accepted for --origin and --destination. Prefer chain names when known (e.g. ethereum, bsc, arbitrum, optimism, polygon).
  4. Address format: Sender and recipient are auto-converted to bytes32 — pass the native address directly. No need to pre-convert.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.