Self-Relay Hyperlane Message

SkillCommunication

Uses the Hyperlane CLI to manually deliver (self-relay) a message between chains that are Ethereum protocol type.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Self-Relay Hyperlane Message skill

What this skill tells your AI

The instructions your AI receives, as published by hyperlane-xyz/hyperlane-monorepo in .claude/skills/self-relay-hyperlane-message/SKILL.md and read by ahel’s review.

Manually deliver a Hyperlane message using the CLI's status --relay command.

Input Parameters

ParameterRequiredDefaultDescription
origin_chainNoDerived from Explorer APIName of the origin chain (auto-derived if not provided)
dispatch_txNo*-Transaction hash of the dispatch (when message was sent)
message_idNo*-The Hyperlane message ID (alternative to dispatch_tx)
registry_pathNoCLI defaultPath to a local registry (overridden if private_rpcs is true)
keyNo$(HYPERLANE_MONOREPO=$(git rev-parse --show-toplevel) hypkey)Private key for signing the relay transaction
private_rpcsNotrueIf true, use private RPCs via local http-registry

* Either dispatch_tx OR message_id must be provided, but not both.

Instructions

Step 0: Find Monorepo Root

The working directory may not be the monorepo root. Find it by looking for CLAUDE.md or package.json with "name": "hyperlane-monorepo":

git rev-parse --show-toplevel

Store this path as MONOREPO_ROOT. All subsequent commands must be prefixed with cd $MONOREPO_ROOT && to ensure correct execution.

Step 1: Validate Inputs

Validate dispatch_tx / message_id:

  • If NEITHER dispatch_tx nor message_id is provided → Error: "Must provide either dispatch_tx or message_id"
  • If BOTH dispatch_tx and message_id are provided → Error: "Provide only one of dispatch_tx or message_id, not both"

Step 2: Start Private RPC Registry (if needed)

If private_rpcs is true:

  1. Force override registry_path to http://localhost:3333
  2. Start the http-registry with /start-http-registry

Step 3: Query Explorer API for Missing Data

Query the Hyperlane Explorer GraphQL API to resolve any missing values (dispatch_tx, origin_chain).

If message_id was provided:

query {
  message_view(
    where: { msg_id: { _eq: "\\x<message_id_without_0x>" } }
    limit: 1
  ) {
    origin_tx_hash
    origin_domain
    is_delivered
  }
}

If dispatch_tx was provided but origin_chain is missing:

query {
  message_view(
    where: { origin_tx_hash: { _eq: "\\x<dispatch_tx_without_0x>" } }
    limit: 1
  ) {
    origin_domain
    is_delivered
  }
}

Use the mcp__hyperlane-explorer__query-graphql tool. Note: bytea fields use \\x prefix without 0x.

Extract values:

  • origin_tx_hash → convert \\x... to 0x... format → set as dispatch_tx
  • origin_domain → set as origin_chain (e.g., "ethereum", "citrea")
  • is_delivered → if true, inform user message is already delivered (no relay needed)

If no message found: Error "Message not found in Hyperlane Explorer"

Step 4: Determine the Key Value

  • If key was provided, use that value directly
  • If key was NOT provided, use the default: $(HYPERLANE_MONOREPO=$(git rev-parse --show-toplevel) hypkey)
  • Important: The default key value is a command substitution. Do NOT execute hypkey directly. Only use it as an environment variable value when running the relay command.

Step 5: Run the Self-Relay Command

Run the following command (append --registry <registry_path> if registry_path is set):

cd $MONOREPO_ROOT && \
LOG_FORMAT=pretty LOG_LEVEL=debug HYP_KEY="<key>" \
pnpm -C typescript/cli hyperlane status --relay --origin <origin_chain> --dispatchTx <dispatch_tx>

Step 6: Cleanup

If private_rpcs was true:

  1. Kill the http-registry using the saved shell/task ID from Step 2
  2. Confirm cleanup was successful

Step 7: Report Results

Surface the output to the user, including:

  • Whether the relay was successful
  • Any errors encountered
  • The destination transaction hash if successful

Examples

Example 1: Using dispatch_tx

cd $MONOREPO_ROOT && \
LOG_FORMAT=pretty LOG_LEVEL=debug HYP_KEY="$(HYPERLANE_MONOREPO=$(git rev-parse --show-toplevel) hypkey)" \
pnpm -C typescript/cli hyperlane status --relay --origin ethereum --dispatchTx 0xabc123...

Example 2: Using message_id only (origin_chain auto-derived)

  1. Find monorepo root: MONOREPO_ROOT=$(git rev-parse --show-toplevel)
  2. Start http-registry in background via /start-http-registry
  3. Query GraphQL for message 0xdef456... → get origin_tx_hash and origin_domain
  4. Check is_delivered - if already delivered, inform user and skip relay
  5. Run:
    cd $MONOREPO_ROOT && \
    LOG_FORMAT=pretty LOG_LEVEL=debug HYP_KEY="$(HYPERLANE_MONOREPO=$(git rev-parse --show-toplevel) hypkey)" \
    pnpm -C typescript/cli hyperlane status --relay --origin <origin_domain> --dispatchTx <origin_tx_hash> --registry http://localhost:3333
    
  6. Kill http-registry process

Signals

GitHub stars
75
Forks
601
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
self-relay-hyperlane-message
Source
github.com/hyperlane-xyz/hyperlane-monorepo