Encode and decode raw Hyperlane messages to/from packed hex bytes using the CLI. Use when you need to construct a message for testing, inspect a raw message from logs or a transaction, or decode a warp transfer body.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add hyperlane-xyz/hyperlane-monorepo --skill hyperlane-message-utils --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Hyperlane Message Utils?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hyperlane-xyz-hyperlane-message-utils)More formats (shields.io, HTML) on the badges page.
---
name: hyperlane-message-utils
description: Encode and decode raw Hyperlane messages to/from packed hex bytes using the CLI. Use when you need to construct a message for testing, inspect a raw message from logs or a transaction, or decode a warp transfer body.
---
# 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
```bash
# 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:**
```bash
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:**
```bash
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:**
```bash
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:**
```bash
hyperlane message encode \
--nonce 1 \
--origin ethereum \
--sender 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf \
--destination bsc \
--recipient 0xBEA3Da2758523301415C609ac4ADEBb638F0eadf
```
**Example — warp transfer:**
```bash
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:
```bash
hyperlane message decode --bytes 0x<message-hex-from-calldata>
```
### 2. Construct a test message for a script
```bash
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
```bash
hyperlane message encode \
--nonce 42 \
--origin 1 \
--sender 0x... \
--destination 42161 \
--recipient 0x... \
| grep "Message ID:"
```
### 4. Round-trip verify encode → decode
```bash
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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!