An Early Look at the Hedera CLI: Simplify, Automate, and Accelerate Development on Hedera

Hedera TeamHedera Team
6 min read

By Michiel Mulders

The Hedera Command Line Interface (CLI) is a powerful tool designed specifically for developers building and scaling applications on the Hedera network. Whether you need to set up test environments, automate repetitive tasks, or manage your end-to-end Hedera development more efficiently, the Hedera CLI helps you streamline processes and reduce manual effort.

Who Should Try the Hedera CLI?

Why Use Hedera CLI?

Key Features of Hedera CLI

1. Accounts and Token Management

The Hedera CLI simplifies the management of essential Hedera functions such as creating accounts, tokens, associating tokens, and performing token transfers.

Below is a sample command to create an account and set an alias for the account so you can easily reference it in other commands:

hcli account create --alias alice -b 100000000 --type ECDSA

Create and manage tokens (note how we reference Alice and Bob).

// Token create
hcli token create --name mytoken --symbol mtk --decimals 2 --initial-supply 1000 --supply-type infinite --admin-key alice --treasury-id 0.0.5401341 --treasury-key bob

// Token associate
hcli token associate -a,--account-id <accountId> -t,--token-id <tokenId>

// Token transfer
hcli token transfer -t,--token-id <tokenId> --to <to> --from <from> -b,--balance <balance>

2. Automate Hedera Consensus Service (HCS) Operations

The Hedera CLI provides comprehensive functionality for the Hedera Consensus Service. You can create topics, submit messages, and find messages right from the command line:

hcli topic create [-s,--submit-key <submitKey>] [-a,--admin-key <adminKey>] [--memo <memo>]

hcli topic message submit -t,--topic-id <topicId> -m,--message <message>

hcli topic message find -t,--topic-id <topicId> -s,--sequence-number <sequenceNumber>

3. Smart Contracts via Hardhat Integration

The CLI integrates with Hardhat, enabling robust smart contract deployment and interaction directly from your command line. Whether deploying a smart contract or interacting with it, the Hedera CLI makes these actions scriptable. The CLI uses the npx command to execute Hardhat scripts.

npx hardhat run ./dist/contracts/scripts/deploy.js --network local
const stateController = require('../../state/stateController.js').default;

async function main() {
  const [deployer] = await ethers.getSigners();

  console.log('Deploying contracts with the account:', deployer.address);

  // The deployer will also be the owner of our token contract
  const ERC721Token = await ethers.getContractFactory('ERC721Token', deployer);
  const contract = await ERC721Token.deploy(deployer.address);
  await contract.waitForDeployment();

  const contractAddress = await contract.getAddress();
  console.log('ERC721 Token contract deployed at:', contractAddress);

  // Store address in script arguments as "erc721address"
  stateController.saveScriptArgument('erc721address', contractAddress);
}

main().catch(console.error);
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ERC721Token is ERC721, Ownable {
    uint256 private _nextTokenId;

    constructor(address initialOwner)
        ERC721("MyERC721Token", "ERCT2")
        Ownable(initialOwner)
    {}

    function safeMint(address to) public onlyOwner returns (uint256) {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        return tokenId;
    }
}

Feature Highlight: Script Blocks

Script Blocks allow you to build automated sequences by chaining multiple commands, significantly simplifying environment setup or complex operations.

Additionally, you can store outputs like token or topic IDs, private keys, and other essential details as variables (format: output:varName), which you can reference in subsequent commands. This enables a high degree of automation for simple tasks and complex flows.

Here's a practical example illustrating a complete automation scenario:

  • Three accounts are created, storing their alias, account ID, and private key.

  • A new token is created, setting account 1 as the admin key and account 2 as the treasury account, referencing variables with the {{variable}} notation.

  • Account 3 is associated with the newly created token.

  • One unit of the token is transferred from the treasury account (account 2) to account 3.

After a 3-second pause, the balance of account 3 is checked, verifying if the token ID is correctly stored in the CLI tool's state.

{
  "name": "transfer",
  "commands": [
   "network use testnet",
    "account create -a alice --args privateKey:privKeyAcc1 --args alias:aliasAcc1 --args accountId:idAcc1",
    "account create -a bob --args privateKey:privKeyAcc2 --args alias:aliasAcc2 --args accountId:idAcc2",
    "account create -a greg --args privateKey:privKeyAcc3 --args alias:aliasAcc3 --args accountId:idAcc3",
    "token create -n mytoken -s MTK -d 2 -i 1000 --supply-type infinite --admin-key {{privKeyAcc1}} --treasury-id {{idAcc2}} --treasury-key {{privKeyAcc2}} --args tokenId:tokenId",
    "token associate --account-id {{idAcc3}} --token-id {{tokenId}}",
    "token transfer -t {{tokenId}} -b 1 --from {{aliasAcc2}} --to {{aliasAcc3}}",
    "wait 3",
    "account balance --account-id-or-alias {{aliasAcc3}} --token-id {{tokenId}}",
    "state view --token-id {{tokenId}}"
  ],
  "args": {}
}

This other example below shows how you can mix hardhat commands and other CLI commands to:

  • Creates a new account and stores the accountId as aliceAccId.

  • Compile all contracts.

  • Deploy a simple storage contract that accepts account IDs.

  • Call the smart contract to store the account ID created in command 1, stored in the variable aliceAccId.


{
  "name": "account-storage",
  "commands": [
    "account create --alias alice --args accountId:aliceAccId",
    "hardhat compile",
    "hardhat run ./dist/contracts/scripts/deploy-acc-storage.js",
    "hardhat run ./dist/contracts/scripts/add-account-id.js"
  ],
  "args": {}
}
const stateController = require('../../state/stateController.js').default;

async function main() {
  const [deployer] = await ethers.getSigners();

  console.log('Deploying contracts with the account:', deployer.address);

  // The deployer will also be the owner of our token contract
  const HederaAccountStorage = await ethers.getContractFactory(
    'HederaAccountStorage',
  );
  const contract = await HederaAccountStorage.deploy();
  await contract.waitForDeployment();

  const contractAddress = await contract.getAddress();
  console.log('HederaAccountStorage contract deployed at:', contractAddress);

  // Store address in script arguments as "accountstorageaddress"
  stateController.saveScriptArgument('accountstorageaddress', contractAddress);
}

main().catch(console.error);
const stateController = require('../../state/stateController.js').default;

async function main() {
  const [deployer] = await ethers.getSigners();
  const accountIdToStore = stateController.getScriptArgument('aliceAccId'); // retrieve alice's account ID
  const contractAddress = stateController.getScriptArgument(
    'accountstorageaddress',
  );

  // The deployer will also be the owner of our token contract
  const HederaAccountStorage = await ethers.getContractFactory(
    'HederaAccountStorage',
  );
  const contract = await HederaAccountStorage.attach(contractAddress);

  // Store the account ID in the contract
  const tx = await contract.addAccountId(accountIdToStore);

  // Wait for the transaction to be mined
  await tx.wait();
  console.log(`Account ID ${accountIdToStore} successfully stored.`);
}

main().catch(console.error);

Give Feedback

Developers are welcome to explore these Hedera CLI features, test their limits, and provide feedback to improve stability and completeness. Your input is essential as we move towards the official release of the Hedera CLI.

Get Started Now

Check out the GitHub repository and start experimenting with the Hedera CLI today. Share your input and help us build a tool that enhances your development experience on Hedera.

0
Subscribe to my newsletter

Read articles from Hedera Team directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Hedera Team
Hedera Team