Skip to content

GrapeInTheTree/chiliz-cli

Repository files navigation

chiliz-cli

Your personal EVM blockchain assistant, from the terminal.

A hybrid CLI+TUI tool built with Go for querying and managing multi-chain EVM transactions — optimized for Chiliz Chain, extensible to any EVM network.

Release Go Report Card License: MIT Downloads CI


Why chiliz-cli?

Most EVM CLI tools are either too low-level (raw RPC calls) or too generic (Foundry's cast has no concept of saved chains, contacts, or token configs). Chiliz CLI fills the gap:

  • Stateful — remembers your chains, tokens, and contacts across sessions via JSON config
  • Dual Data Sources — combines RPC (real-time balance, blocks) with Explorer API (transaction history, token discovery) in a single command
  • AI Agent Friendly--json output on every command, designed for chiliz address 0x... --json | jq
  • Chiliz-First — built for a chain with no dedicated CLI tooling (Chiliz is a go-ethereum fork)
  • Hybrid — same binary runs as a scriptable CLI or an interactive TUI

Think of it as cast meets a personal wallet manager.

Quick Start

# Install (pick one)
brew tap GrapeInTheTree/tap && brew install chiliz   # Homebrew
go install github.com/GrapeInTheTree/chiliz-cli/cmd/chiliz@latest  # Go

# Initialize config (Chiliz Mainnet + Spicy Testnet)
chiliz init

# Start querying
chiliz chain-info                    # Chiliz mainnet status
chiliz validators                    # validator set
chiliz address 0xC3B2...             # any address
chiliz --chain "spicy" chain-info    # Spicy testnet

Install

Homebrew (macOS / Linux)

brew tap GrapeInTheTree/tap
brew install chiliz

Go Install

go install github.com/GrapeInTheTree/chiliz-cli/cmd/chiliz@latest

Download Binary

Pre-built binaries for macOS (Intel/Apple Silicon) and Linux (amd64/arm64) on the Releases page.

Build From Source

git clone https://github.com/GrapeInTheTree/chiliz-cli.git
cd chiliz-cli
go build -o chiliz ./cmd/chiliz

How It Works

chiliz address 0xC3B2...D2c49
    │
    ├── RPC (go-ethereum ethclient) ──────────────────> Chiliz Node
    │     ├── eth_getBalance         → native balance     (rpc.ankr.com/chiliz)
    │     ├── eth_getTransactionCount → nonce
    │     └── eth_getCode            → EOA or contract
    │
    └── Explorer API (Chiliscan/Routescan) ───────────> Indexer
          ├── txlist                  → recent transactions
          └── addresstokenbalance    → all ERC-20 holdings

    ──> output.Print(jsonMode, AddressInfo)
          ├── human-readable table (default)
          └── JSON (--json flag)
Data Source Why
Native balance, nonce, code RPC eth_* Standard EVM methods
Tx by hash + receipt RPC Direct lookup
Block by number RPC Direct lookup
Gas price, chain ID RPC Real-time state
Tx history by address Explorer API No RPC method exists (eth_getTransactionsByAddress doesn't exist)
All token holdings Explorer API Token discovery requires an indexer

CLI Usage

chiliz                              Interactive TUI mode (no subcommand)
chiliz address <addr>               Address info: balance, nonce, tx history, token holdings
chiliz tx <hash>                    Transaction details with receipt
chiliz block [number|latest]        Block information
chiliz chain-info                   Chain status: latest block, gas price
chiliz call <contract> <sig> [args] Read-only contract call (eth_call)
chiliz validators                   Chiliz validator set and staking status
chiliz staking <addr>               Personal staking positions and rewards
chiliz token <contract>             Token metadata, price, and social links
chiliz contract <addr>              Contract info: name, compiler, deployer, verified
chiliz holders <token>              Top token holders and total holder count
chiliz logs --address --event       On-chain event log filtering via eth_getLogs (RPC)
chiliz rpc <method> [params]        Raw JSON-RPC escape hatch
chiliz init                         Initialize config (~/.chiliz/)
chiliz version                      Print version and build info

Global flags:
  --chain <name>     Blockchain network (default: first in chains.json)
  --json             Machine-readable JSON output
  --config <path>    Config directory path
  -h, --help         Help for any command

Contact Name Resolution

All address commands support contact names from contacts.json:

chiliz address danial           # resolves to 0xef33...d93c
chiliz staking kayen            # resolves to 0x86d3...8897
chiliz address 0xC3B2...D2c49   # direct address still works

chiliz address

Comprehensive address overview — 5 concurrent fetches (3 RPC + 2 Explorer) for fast response.

$ chiliz address 0xC3B2A6D869868916b1f5D46f9b7C62eD2f1D2c49

  Address:  0xC3B2A6D869868916b1f5D46f9b7C62eD2f1D2c49
  Chain:    Chiliz Chain (88888)
  Balance:  5045.818772 CHZ
  Nonce:    310
  Type:     EOA

  Token Holdings:
    PEPPER     12340.000000

  Recent Transactions (last 10):
    Hash            Method       Value              Time
    -----------------------------------------------------------------
    0x9f97...9981   Transfer     +3631.087415       4d ago
    0x12a8...b3e5   Transfer     +316.752300        7d ago
    0x1a79...a414   Transfer     -316.752300        7d ago
    ...

chiliz tx

Full transaction details including receipt, gas breakdown, and event logs.

$ chiliz tx 0x9f978b07484bb439e790079afe192e0a562a93a26c9d893ea8001ddda88e9981

  Tx Hash:    0x9f978b...88e9981
  Status:     success
  Block:      32492204
  Time:       2026-03-23 00:23:15 UTC
  From:       0xa3DF8880d1D1BfC5Bea208AC3f1662420B2E2657
  To:         0xC3B2A6D869868916b1f5D46f9b7C62eD2f1D2c49
  Value:      3631.087415 CHZ
  Gas Price:  5001.00 Gwei
  Gas Used:   21000 / 21000
  Tx Fee:     0.105021 CHZ
  Nonce:      5343
  Logs:       0 events

chiliz block

$ chiliz block latest

  Block:       #32617854
  Hash:        0x3f1317eb...75aeb5a
  Time:        2026-03-27 09:05:54 UTC
  Miner:       0xc10ae5Cd2C63E4065f81E241c93237E06E12d41b
  Gas Used:    70012 / 30000000
  Base Fee:    2500.00 Gwei
  Txs:         1 transactions

chiliz call

Generic read-only contract calls — query any smart contract function.

# ERC-20 totalSupply
$ chiliz call 0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67 "totalSupply()(uint256)"
  8760093706618541126999998364250000

# Token name and decimals
$ chiliz call 0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67 "name()(string)"
  PEPPER

# Chiliz validator list (system contract)
$ chiliz call 0x0000000000000000000000000000000000001000 "getValidators()(address[])"
  [0x8d9B6aB3..., 0xBf968b8a..., 0x31dB8118..., ...]

# Check if address is a validator
$ chiliz call 0x0000000000000000000000000000000000001000 "isValidator(address)(bool)" 0x8d9B6aB3Fe8EbF16d9242e48feFB89360fa62820
  true

# JSON output
$ chiliz call 0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67 "totalSupply()(uint256)" --json
{
  "contract": "0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67",
  "method": "totalSupply()",
  "values": ["8760093706618541126999998364250000"],
  "raw": "0x000000000000000000000000000000000001afe7ed5e433cdebfb05bd38def90"
}

# Raw hex (no output types specified)
$ chiliz call 0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67 "totalSupply()"
  0x000000000000000000000000000000000001afe7ed5e433cdebfb05bd38def90

chiliz validators

Chiliz-exclusive: query on-chain Staking + Governance contracts for validator status with APY and Voting Power.

$ chiliz validators

  Chiliz Chain Validators (13 active)

  #    Address         Status     Staked           APY        VP         Commission
  ----------------------------------------------------------------------------------
  1    0x8d9B...2820   Active     293.33M CHZ      18.32%     12.40%     1.0%
  2    0xBf96...0B5f   Active     291.01M CHZ      17.57%     12.30%     5.0%
  3    0x31dB...B074   Active     256.79M CHZ      16.65%     10.85%     10.0%
  4    0xa90d...A00e   Active     222.23M CHZ      17.57%     9.39%      5.0%
  ...

APY is estimated from on-chain rewards data (same approach as the staking web UI). Voting Power matches exactly.

chiliz chain-info

$ chiliz chain-info --json
{
  "name": "Chiliz Chain",
  "chain_id": 88888,
  "rpc_url": "https://rpc.ankr.com/chiliz",
  "latest_block": 32617854,
  "gas_price": "2501.00 Gwei",
  "currency_symbol": "CHZ"
}

JSON Output

Every command supports --json for piping and AI agent consumption:

chiliz address 0xC3B2... --json | jq .native_balance
chiliz chain-info --json | jq .latest_block
chiliz tx 0x9f97... --json | jq '{status, fee: .tx_fee}'

TUI Usage

Run chiliz with no arguments for interactive mode.

┌─────────────────────────────────────┐
│  🔗  GO-ETHEREUM-BUTLER  🔗        │
│  Multi-Chain EVM Transaction Manager│
│                                     │
│  ┌─────────────────────────────┐    │
│  │  Main Menu                  │    │
│  │                             │    │
│  │  📤 Send Transaction        │    │
│  │  💰 Check Balance      ◄   │    │
│  │  🚪 Exit                   │    │
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘
Key Action
up / k Move cursor up
down / j Move cursor down
enter Select / Confirm
esc Back to main menu
ctrl+c Quit
0-9, . Amount input (send flow)
backspace Delete last character

Check Balance — Select wallet > chain > token (native or ERC-20) > view balance

Send Transaction — Select wallet > chain > token > recipient > enter amount > confirm > tx hash

Configuration

Chiliz CLI uses JSON config files. All are gitignored by default — create your own from the examples below.

chains.json

[
  {
    "name": "Chiliz Chain",
    "rpc_url": "https://rpc.ankr.com/chiliz",
    "chain_id": 88888,
    "currency_symbol": "CHZ",
    "logo_url": "",
    "explorer_api_url": "https://api.routescan.io/v2/network/mainnet/evm/88888/etherscan/api"
  }
]
Field Required Description
name Yes Display name, also used with --chain flag
rpc_url Yes Any EVM-compatible JSON-RPC endpoint
chain_id Yes EIP-155 chain ID
currency_symbol Yes Native token symbol (CHZ, ETH, etc.)
logo_url No Optional logo URL
explorer_api_url No Etherscan-compatible API URL. Enables tx history and token discovery. Without it, CLI still shows RPC-based data.

tokens.json

[
  {
    "symbol": "PEPPER",
    "name": "Pepper Token",
    "address": "0x60F397acBCfB8f4e3234C659A3E10867e6fA6b67",
    "decimals": 18,
    "chain_id": 88888,
    "logo_url": ""
  }
]
  • decimals must match the contract (18 for most, 6 for USDC/USDT, 8 for WBTC)
  • chain_id must match a chain in chains.json
  • Native tokens (CHZ, ETH) are automatically available — no entry needed
  • Same token on different chains needs separate entries

contacts.json

[
  { "name": "My Friend", "address": "0x..." },
  { "name": "Team Wallet", "address": "0x..." }
]

Used by the TUI send flow for recipient selection.

.env

BUTLER_WALLET_MAIN=your_private_key_here_without_0x_prefix
BUTLER_WALLET_TEST=your_test_private_key_here

Copy from .env.example. Private keys are never logged, cached, or committed to git. CLI read-only commands (address, tx, block, chain-info) do not access private keys at all.

Config Directory Resolution

Chiliz CLI searches for config files in this order:

  1. --config /path/to/dir flag (explicit)
  2. CHILIZ_CONFIG_DIR environment variable
  3. ~/.chiliz/ directory (if chains.json exists there)
  4. Current working directory (default)

This allows installing chiliz globally via brew and keeping configs in ~/.chiliz/.

Architecture

cmd/chiliz/
  main.go                       Entry point: Cobra Execute()
  cmd/
    root.go                     Root command + global flags + PersistentPreRunE
    tui.go                      TUI launcher (no-args fallback)
    address.go                  chiliz address — parallel RPC + Explorer
    tx.go                       chiliz tx — tx + receipt lookup
    block.go                    chiliz block — block by number
    chaininfo.go                chiliz chain-info — chain status
    call.go                     chiliz call — generic contract reads (eth_call)

internal/
  domain/
    models.go                   Chain, Token, Wallet, Contact structs
    output.go                   AddressInfo, TxDetail, BlockInfo, ChainStatus, CallResult

  infra/
    config/config.go            JSON/env config loading + path resolution
    ethereum/
      client.go                 RPC: balance, nonce, code, blocks, tx, gas, call
      abi_helper.go             Dynamic ABI encoding/decoding (no abigen needed)
      erc20.go                  ERC-20: balance, transfer, formatting
      abi/erc20.json            Standard ERC-20 ABI
      contracts/erc20.go        Auto-generated Go bindings (abigen)
    explorer/
      etherscan.go              Chiliscan API: tx history, token discovery

  output/
    formatter.go                Human + JSON dual formatter

  tui/
    app.go                      Bubble Tea router
    style/style.go              Lipgloss styles
    pages/                      mainmenu, balance, send
Design Decisions

Cobra + Bubbletea hybrid — Cobra routes subcommands. No args = Bubbletea TUI. Single binary, same infra layer shared. This follows the pattern used by lazygit, k9s, and other Go CLI/TUI hybrids.

Package-level appContext — CLI commands share resolved config/chain/explorer via a package-level struct in root.go. Appropriate for a CLI tool (single execution path, no concurrency at the command level). Not suitable for a server; would need DI then.

Each RPC function creates its own ethclientDial → defer Close → call → return. For a CLI that runs one command and exits, connection pool overhead isn't worth the lifecycle management complexity.

Explorer graceful degradation — If a chain has no explorer_api_url or the API is down, chiliz address still shows balance, nonce, and contract status from RPC. Explorer sections are simply omitted.

Output types in domain/AddressInfo, TxDetail, etc. are stable JSON contracts. Placing them in domain/ keeps them framework-agnostic and reusable across CLI, TUI, and future API layers.

pow10 uses big.Int — The original int64-based pow10() would silently overflow for tokens with >18 decimals. Fixed to use big.Int.Exp() which is safe for any decimal count.

Dynamic ABI via abi_helper.gochiliz call uses abi.ParseSelector + Arguments.Pack/Unpack for runtime ABI encoding without JSON files. The same module will be reused by future commands (validators, staking, event logs). ParseCallSignature splits cast-style signatures via parenthesis depth counting because abi.ParseSelector rejects trailing characters.

Releasing

Releases are automated via GoReleaser + GitHub Actions.

# 1. Commit your changes
git add . && git commit -m "feat: ..."

# 2. Tag and push
git tag v0.3.0
git push && git push --tags

# 3. GitHub Actions automatically:
#    - Cross-compiles linux/darwin × amd64/arm64
#    - Creates GitHub Release with changelog and binaries
#    - Updates Homebrew formula in GrapeInTheTree/homebrew-tap

Users upgrade with brew upgrade chiliz or go install ...@latest.

Release Infrastructure Details
File Purpose
.goreleaser.yml Build matrix (linux/darwin × amd64/arm64), archive format, Homebrew tap config
.github/workflows/release.yml Triggered on v* tag push, runs goreleaser release --clean

Required GitHub secrets:

  • HOMEBREW_TAP_TOKEN — Fine-grained PAT with repo scope on GrapeInTheTree/homebrew-tap
  • GITHUB_TOKEN — Automatic, used for creating GitHub Releases

Shell Completion

Chiliz CLI supports tab completion for bash, zsh, and fish:

# Bash
chiliz completion bash > /etc/bash_completion.d/chiliz

# Zsh (add to ~/.zshrc: fpath=(~/.zsh/completions $fpath))
chiliz completion zsh > ~/.zsh/completions/_chiliz

# Fish
chiliz completion fish > ~/.config/fish/completions/chiliz.fish

Development

go build -o chiliz ./cmd/chiliz    # Build
go test ./...                       # Test (22 cases)
go vet ./...                        # Lint
tail -f chiliz.log                  # TUI logs
Regenerate ERC-20 Bindings

If you update internal/infra/ethereum/abi/erc20.json:

go install github.com/ethereum/go-ethereum/cmd/abigen@latest
abigen --abi internal/infra/ethereum/abi/erc20.json \
       --pkg contracts --type ERC20 \
       --out internal/infra/ethereum/contracts/erc20.go
Extending the App

No code changes needed:

What File
Add EVM chain chains.json (include explorer_api_url for tx history)
Add ERC-20 token tokens.json (decimals must match contract)
Add contact contacts.json

Code changes needed:

What Where
Add CLI command Create cmd/chiliz/cmd/<name>.go, register in root.go init()
Add wallet internal/infra/config/config.go LoadWallets() + .env
Add TUI page Create internal/tui/pages/<name>/model.go, register in app.go
Add blockchain query Add to internal/infra/ethereum/client.go
Add explorer query Add to internal/infra/explorer/etherscan.go
Add output type Add struct to internal/domain/output.go, add case in internal/output/formatter.go
Add contract type Place ABI in abi/, run abigen, use bindings in new file

Technology Stack

Component Technology
Language Go 1.25+
CLI Framework spf13/cobra v1.10.2
TUI Framework charmbracelet/bubbletea v1.3.10
TUI Styling charmbracelet/lipgloss v1.1.0
EVM Client ethereum/go-ethereum v1.16.7
Env Loader joho/godotenv v1.5.1
Release GoReleaser + GitHub Actions
Explorer API Chiliscan (Routescan, Etherscan-compatible)

Security

  • Private keys live only in .env (gitignored) and are loaded on-demand at signing time via config.GetPrivateKey()
  • Keys are never cached in memory, logged, or written to any file
  • CLI read-only commands never access private keys
  • Git history audited: no secrets have ever been committed
  • Log file permissions set to 0600 (owner read/write only)
  • .env, chains.json, tokens.json, contacts.json are all gitignored

License

MIT

About

A hybrid CLI+TUI tool for querying and managing multi-chain EVM transactions — optimized for Chiliz Chain.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors