This guide assists you in setting up the Teranode project on your machine. The below assumes you are running a recent version of Mac OS on Apple Silicon (arm64). GoBDK ships prebuilt static libraries for darwin/arm64, linux/amd64 and linux/arm64 only — Intel Macs (darwin/amd64) are not a supported build target.
- Install Go
- Set Go Environment Variables
- Python and Dependencies
- Clone the Project and Install Dependencies
- Configure Settings
- Prerequisites for Running the Node
- Run the Node
- Troubleshooting
Download and install the latest version of Go. As of September 2026, it's 1.27.0.
Test Installation:
Open a new terminal and execute:
go versionIt should display go1.27.0 or above.
Add these lines to .zprofile or .bash_profile, depending on which one your development machine uses:
export PATH="$PATH:$(go env GOPATH)/bin"
export GOPATH="$(go env GOPATH)"
export GOBIN="$(go env GOPATH)/bin"Test Configuration:
Open a new terminal and execute:
echo $GOPATH
echo $GOBINBoth should display paths related to Go.
brew install pythonBy default, Homebrew will install Python 3.x and create symlinks like python3 and pip3. You can optionally create a symlink for python and pip if you want shorter commands (but check if they already exist first):
ln -s /opt/homebrew/bin/python3 /opt/homebrew/bin/python # might already exist
ln -s /opt/homebrew/bin/pip3 /opt/homebrew/bin/pip # might already existBecause of PEP 668 and Homebrew’s “externally-managed-environment” setup, you can’t do pip install ... directly into the system-wide Python.
Instead, create and activate a virtual environment:
python3 -m venv ~/my_python_env # choose any path you like
source ~/my_python_env/bin/activateAfter activating, your shell should show something like (my_python_env) as a prefix.
Once your virtual environment is active, you can safely use pip to install packages without system conflicts:
python -m pip install --upgrade pip
pip install PyYAMLpython -c "import yaml; print(yaml.__version__)"This should print out the installed PyYAML version (e.g., 6.0.2 or similar).
If you need PyYAML as part of a standalone command-line tool, you could use pipx instead:
brew install pipx
pipx install PyYAMLHowever, most Teranode workflows will need PyYAML as a library for scripts, so a virtual environment is usually best.
Clone the project:
git clone git@github.com:bsv-blockchain/teranode.gitInstall all dependencies:
Execute:
cd teranode
# This will install all required dependencies (protobuf, golangci-lint, etc.)
make installNote: If you receive an error
ModuleNotFoundError: No module named 'yaml'error, refer to this issue for a potential fix. Example:PYTHONPATH=$HOME/Library/Python/3.9/lib/python/site-packages make install #Make sure the path is correct for your own python version
Teranode uses two configuration files:
settings.conf- Contains sensible defaults for all environments. You should NOT modify this file as part of the scope of this guide.settings_local.conf- Contains developer-specific and deployment-specific settings
-
In your project directory, create a file
settings_local.conf. This file is used for your personal development settings, and it's not tracked in source control. -
Introduce any settings override in
settings_local.confthat you might require for your development. Use thesettings.confas a reference for common settings and their default values. -
The settings you are adding will use a prefix (settings context) that identifies your context. By default, your settings context should be
dev.. You can further refine this by using a more specific prefix, such asdev.johnordev.me. However, it is recommended to use the default prefixdev., and only refine it in very specific cases.
In order for your node to read your custom lines, you set SETTINGS_CONTEXT to match the prefix you used (i.e., dev).
In zsh, open ~/.zprofile (or ~/.zshrc). In bash, open ~/.bash_profile (or ~/.bashrc).
Add:
export SETTINGS_CONTEXT=dev(If you have used a richer prefix, such as dev.john, you would set SETTINGS_CONTEXT=dev.john)
After editing, reload your shell config:
source ~/.zprofile(or the equivalent for your shell).
-
Echo the environment variable to ensure it's set correctly:
echo $SETTINGS_CONTEXT
Should print
dev. -
Run or restart your node. Check logs or console output to confirm it's picking up the lines with
dev.
Teranode uses Docker containers for running dependencies like Kafka and PostgreSQL. For Mac developers, we recommend using OrbStack - a fast, lightweight Docker Desktop alternative optimized for macOS.
Why OrbStack?
- Faster: 2-3x faster than Docker Desktop for container startup and file operations
- Lighter: Uses significantly less CPU and memory
- Native: Built specifically for macOS with better integration
- Compatible: Drop-in replacement for Docker Desktop - all Docker commands work the same
Installation:
- Download OrbStack from orbstack.dev
- Open the downloaded file and drag OrbStack to your Applications folder
- Launch OrbStack from your Applications folder
- Follow the brief setup wizard
Verify installation:
docker --versionOnce OrbStack is installed and running, start PostgreSQL with:
# Start PostgreSQL in Docker
./scripts/postgres.shNote on Kafka: Development mode uses in-memory Kafka by default (no setup required). For production-like testing with Docker-based Kafka, see Kafka Settings Reference. If you configure your settings to use Aerospike for UTXO storage, you'll also need to run the Aerospike script:
# Start Aerospike in Docker ./scripts/aerospike.sh
You can run the entire node with the following command:
SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] go run .If no errors are seen, you have successfully installed the project and are ready to start working on the project or running the node.
Note that the node is initialized in IDLE mode by default. You'll need to transition it to RUNNING mode to start processing transactions.
The Teranode-CLI allows you to interact with Teranode services. You can use it to transition the node to different states, query its current state, and perform various maintenance operations. For a comprehensive guide on using the Teranode-CLI as a developer, see the Developer's Guide to Teranode-CLI.
Build the Teranode-CLI tool with:
go build -o teranode-cli ./cmd/teranodecliOnce built, you can run commands directly:
# Get current FSM state
SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] ./teranode-cli getfsmstate
# Set FSM state to RUNNING
SETTINGS_CONTEXT=dev.[YOUR_CONTEXT] ./teranode-cli setfsmstate --fsmstate runningThe Teranode-CLI provides several commands:
| Command | Description |
|---|---|
getfsmstate |
Get the current FSM State |
setfsmstate |
Set the FSM State (with --fsmstate flag) |
settings |
View system configuration |
aerospikereader |
Read transaction data from Aerospike |
filereader |
Read and process files |
seeder |
Seed initial blockchain data |
bitcointoutxoset |
Convert Bitcoin data to UTXO set |
utxopersister |
Manage UTXO persistence |
export-blocks |
Export blockchain to CSV |
import-blocks |
Import blockchain from CSV |
checkblocktemplate |
Check block template |
For general help and a list of available commands:
# General help
./teranode-cli
# Command-specific help
./teranode-cli setfsmstate --helpThe CLI will use your development settings as specified by your SETTINGS_CONTEXT environment variable.
To transition the node from IDLE to RUNNING mode, use:
# Get current FSM state
SETTINGS_CONTEXT=dev ./teranode-cli getfsmstate
# Set FSM state to RUNNING
SETTINGS_CONTEXT=dev ./teranode-cli setfsmstate --fsmstate runningAfter executing these commands, your log should show a successful transition:
[Blockchain Client] FSM successfully transitioned from IDLE to state:RUNNINGTeranode supports debugging using Delve, the Go debugger. You can use any IDE that supports Delve, including VS Code, GoLand, or the Delve CLI directly.
To debug Teranode during local development, you have several options:
This is the most reliable method and works on all platforms including M3/M4 Macs.
-
Build with debug symbols:
DEBUG=true make build
This enables debug flags (
-N -l) that disable optimizations and inlining, making debugging easier. -
Run with your IDE's debugger:
- GoLand: Use "Run" → "Debug" or press
Ctrl+D(Linux/Windows) /⌃D(Mac) - VS Code: Use "Run and Debug" panel or press
F5after configuring launch.json
- GoLand: Use "Run" → "Debug" or press
Note: This method does not work on Apple M3/M4 Macs due to architecture limitations.
- Build and start Teranode as normal
- Find the process ID:
ps aux | grep teranode - Attach your debugger to the PID:
- GoLand: "Run" → "Attach to Process"
- VS Code: Use "attach" configuration in launch.json
This method allows you to start the application with Delve and attach your IDE remotely:
-
Install Delve (if not already installed):
go install github.com/go-delve/delve/cmd/dlv@latest
-
Start Teranode with Delve:
dlv exec ./teranode.run --headless --listen=:2345 --api-version=2 --accept-multiclient -
Attach your IDE to Delve:
- GoLand: Create a "Go Remote" run configuration pointing to
localhost:2345 - VS Code: Use a remote attach configuration in launch.json with port 2345
- GoLand: Create a "Go Remote" run configuration pointing to
For debugging Teranode running in Kubernetes environments:
-
See the Remote Debug Guide for detailed instructions on:
- Configuring the Kubernetes cluster for remote debugging
- Port forwarding the debugger
- Connecting with VS Code, GoLand, or Delve CLI
- Debugging multiple services simultaneously
Should you have errors with dependencies, try running the following commands:
go clean -cache
go clean -modcache
rm go.sum
go mod tidy
go mod downloadThis will effectively reset your cache and re-download all dependencies.
As an alternative to the manual steps above, you can use the teranode-dev CLI tool to automate the entire local setup process. It asks a few questions and handles everything else - prerequisites, settings, Docker containers, and building.
make build-teranode-dev./teranode-dev initThe wizard will ask for:
- Your developer name (for
SETTINGS_CONTEXT) - UTXO storage backend (SQLite, PostgreSQL, or Aerospike)
- Network (regtest, testnet, or mainnet)
- Whether to use Docker-based Kafka (default: in-memory)
- Whether to enable monitoring (Grafana + Prometheus)
- Whether to enable tracing (Jaeger)
It then automatically:
- Checks prerequisites (Go, Docker, Python)
- Generates
settings_local.confentries - Creates data directories
- Configures
/etc/hostsfor Kafka (if selected) - Starts Docker containers and waits for health
- Builds
teranode.runwith the correct build tags
./teranode-dev up # Start infrastructure containers (postgres, kafka, etc.)
./teranode-dev down # Stop infrastructure containers
./teranode-dev clean # Wipe data directory (with confirmation)If a service is already running on the expected port (e.g. a native PostgreSQL), the tool will skip starting a Docker container for it.
./teranode-dev start # Start teranode daemon in background with log rotation
./teranode-dev stop # Stop teranode daemon (graceful, then force after 5s)The node starts directly in RUNNING state (no need to manually set the FSM state).
On regtest, you can generate blocks for testing:
./teranode-dev generate # Generate 1 block
./teranode-dev generate 10 # Generate 10 blocksThis calls the node's RPC generate command. It only works on networks where CPU mining is supported (regtest). On other networks it will return an error.
Call any Bitcoin JSON-RPC method directly without needing curl or remembering auth credentials:
./teranode-dev rpc # List all available RPC commands
./teranode-dev rpc getblockchaininfo # Query chain state
./teranode-dev rpc getblockhash 0 # Get genesis block hash
./teranode-dev rpc getblock <hash> 2 # Get block with verbosity level 2
./teranode-dev rpc getpeerinfo # List connected peers
./teranode-dev rpc sendrawtransaction <hex> # Broadcast a raw transactionParameters are automatically converted to the correct JSON types (numbers, strings, booleans).
./teranode-dev status # Show running services, health checks, FSM state, chain tip
./teranode-dev monitor # Live TUI dashboard for real-time node monitoring
./teranode-dev logs # Interactive log viewer with filtering and search
./teranode-dev settings # Print all resolved settings as JSON
./teranode-dev doctor # Check prerequisites, configuration, and chain consistency
./teranode-dev diagnose # Detailed health checks (gRPC, HTTP, Kafka, Postgres, Aerospike)
./teranode-dev diagnose --config # Validate configuration for common issues
./teranode-dev diagnose --json # Machine-readable outputThe doctor command also detects chain/genesis mismatches - if you change your configured network without clearing the database, it will offer to either delete the stored data or change the network setting to match.
The logs command supports flags:
./teranode-dev logs --file ./logs/teranode.log # Custom log file path
./teranode-dev logs --buffer 20000 # Keep more entries in memoryFor CI or scripting:
./teranode-dev init --non-interactive --name=liam --utxo=sqlite --network=regtestRunning init again presents your previous choices as defaults - just press enter to keep them. This is useful for changing a single setting (e.g. switching from sqlite to postgres) without re-entering everything.