Most developers first encounter Bitcoin through polished mobile wallets or sleek web interfaces. But that's like learning programming by only using drag-and-drop tools—you miss the fundamental mechanics that make everything work.
As programmers, we understand that true mastery comes from getting our hands dirty with the underlying systems. When you run your own Bitcoin node and interact with it directly via the command line, you're not just using Bitcoin—you're speaking its native language.
This guide will take you from spinning up your first Bitcoin node to understanding UTXOs, crafting transactions, and managing multiple wallets. By the end, you'll have the foundation needed to build Bitcoin applications.
Why Command Line Bitcoin Matters
With command-line Bitcoin, you gain:
- Unfiltered access to Bitcoin's data structures as your node stores them
- Complete sovereignty—no third-party APIs, no rate limits, no downtime
- Scripting capabilities for automation and custom workflows
- Deep understanding of Bitcoin's UTXO model and transaction structure
- Foundation knowledge for building Bitcoin applications
Prerequisites
You'll need:
- Basic command-line comfort
- Understanding of JSON (Bitcoin Core returns data in JSON format)
- About 100MB disk space for our regtest experiments
Part 1: Setting Up Your Bitcoin Laboratory
Installing Bitcoin Core
Bitcoin Core provides two essential tools:
-
bitcoind
: The full node daemon that validates and relays transactions -
bitcoin-cli
: Your command-line interface to the daemon
Download the latest version from bitcoin.org/en/download
For this tutorial, we'll use regtest mode—Bitcoin's built-in testing environment where you're the only miner, blocks generate instantly, and you can experiment safely.
Starting Your Private Bitcoin Network
# Start bitcoind in regtest mode
bitcoind -regtest -daemon
# Verify it's running
bitcoin-cli -regtest getnetworkinfo
Pro tip: Create an alias to save typing:
alias bcli="bitcoin-cli -regtest"
Now you can use bcli
instead of typing the full command each time.
Part 2: Your First Bitcoin Genesis Moment
Understanding Bitcoin's State
Bitcoin doesn't track account balances like a traditional database. Instead, it tracks Unspent Transaction Outputs (UTXOs)—chunks of bitcoin that can be spent.
Check your initial state:
bcli getblockchaininfo
Notice "blocks": 0
—you're at the genesis block with no bitcoins in existence yet.
Creating Your First Wallet (Alice)
bcli createwallet "alice"
Output:
{
"name": "alice",
"warning": ""
}
Your First Mining Operation
Now for the magic moment—creating bitcoin from nothing through mining:
# Generate a new address for Alice to receive mining rewards
ADDRESS=$(bcli -rpcwallet=alice getnewaddress "mining-rewards")
echo "Mining to Alice's address: $ADDRESS"
# Mine 101 blocks (we need 101 to spend the first block's reward)
bcli generatetoaddress 101 $ADDRESS
What just happened?
- Address Generation: Created a Bitcoin address where coins can be sent
- Block Creation: Created 101 new blocks, each paying 50 BTC to Alice's address
- Coinbase Maturity: Bitcoin requires 100 confirmations before newly mined coins can be spent
Let's verify Alice's balance:
bcli -rpcwallet=alice getbalance
# Output: 50.00000000
Alice now has 50 BTC! (Only from the first block—the other rewards are still maturing)
Part 3: Understanding Bitcoin's Data Structures
Examining UTXOs
Let's see what bitcoin "ownership" actually means:
bcli -rpcwallet=alice listunspent
You'll see something like:
[
{
"txid": "f3d7f85e0b3c91e4d8c4b7abc1d0e3f2a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4",
"vout": 0,
"address": "bcrt1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"amount": 50.00000000,
"confirmations": 101,
"spendable": true
}
]
This UTXO represents:
- txid: The transaction that created this output (a coinbase transaction)
- vout: Output index (0 for coinbase transactions)
- amount: 50 BTC
- confirmations: How deep it is in the blockchain (must be >100 to spend)
Exploring Block Structure
Let's examine the block containing Alice's first coinbase transaction:
# Get the hash of block #1
BLOCK_HASH=$(bcli getblockhash 1)
echo "Block 1 hash: $BLOCK_HASH"
# Get detailed block information
bcli getblock $BLOCK_HASH 2
Key observations from the output:
- coinbase: The input field contains arbitrary data (no previous transaction)
- vout: Single output paying 50 BTC to Alice's address
- scriptPubKey: The locking script that defines how this UTXO can be spent
Part 4: Multi-Wallet Operations and Your First Transaction
Creating Bob's Wallet
Let's create a second wallet and demonstrate Bitcoin's peer-to-peer nature:
# Create Bob's wallet
bcli createwallet "bob"
# Generate an address for Bob
BOB_ADDRESS=$(bcli -rpcwallet=bob getnewaddress "received-from-alice")
echo "Bob's address: $BOB_ADDRESS"
Alice Sends Bitcoin to Bob
Now Alice will send some of her mined bitcoin to Bob:
# Alice sends 10 BTC to Bob
TXID=$(bcli -rpcwallet=alice sendtoaddress $BOB_ADDRESS 10.0)
echo "Transaction ID: $TXID"
# Mine a block to confirm the transaction
bcli generatetoaddress 1 $(bcli -rpcwallet=alice getnewaddress)
Understanding What Happened
Let's examine this transaction:
bcli getrawtransaction $TXID true
You'll see a transaction with:
- vin: Input spending Alice's 50 BTC UTXO
-
vout: Two outputs:
- 10 BTC to Bob's address
- ~40 BTC back to Alice as change (minus a small mining fee)
This demonstrates Bitcoin's fundamental principle: UTXOs must be spent in full. Alice couldn't spend just 10 BTC from her 50 BTC UTXO—she had to spend the entire UTXO and create new outputs.
Checking Final Balances
# Check Alice's balance
echo "Alice's balance: $(bcli -rpcwallet=alice getbalance)"
# Check Bob's balance
echo "Bob's balance: $(bcli -rpcwallet=bob getbalance)"
# List Bob's UTXOs to see the received bitcoin
bcli -rpcwallet=bob listunspent
You should see:
- Alice: ~40 BTC (50 - 10 - small fee)
- Bob: 10 BTC
Transaction History
View the transaction from both perspectives:
# Alice's transaction history
echo "=== Alice's Transactions ==="
bcli -rpcwallet=alice listtransactions
# Bob's transaction history
echo "=== Bob's Transactions ==="
bcli -rpcwallet=bob listtransactions
Alice will see a "send" transaction with a negative amount, while Bob will see a "receive" transaction with a positive amount—the same transaction viewed from different wallets.
Cleanup
When you're done experimenting:
# Stop the daemon
bcli stop
Conclusion
Congratulations! You've just experienced Bitcoin's core mechanics firsthand:
- Operated your own full Bitcoin node in regtest mode
- Mined blocks and created bitcoin from nothing through coinbase transactions
- Understood UTXOs as Bitcoin's fundamental building blocks
- Created multiple wallets and sent bitcoin between them
- Explored Bitcoin's transaction structure and block anatomy
You now understand that Bitcoin isn't about account balances—it's about a graph of UTXOs that can be unlocked and spent using cryptographic signatures. Every transaction consumes existing UTXOs and creates new ones, forming an unbroken chain back to coinbase transactions.
This command-line foundation is essential for any serious Bitcoin development work. Whether you're building wallets, payment processors, or blockchain analytics tools, understanding how Bitcoin works at this level will make you a more effective developer.
In the next part of this series, we'll dig deep into Bitcoin scripting with JavaScript, exploring how to programmatically create transactions, implement custom spending conditions, and build sophisticated Bitcoin applications using popular libraries like bitcoinjs-lib.
The blockchain is yours to explore—one command at a time.
Top comments (0)