The following commands can be used to follow along with the Bitcoin Core demo from the August 5, 2026 Gordian Developer meeting.

Installations

This CLI tutorial requires the installation of five tools: bitcoin-cli, envelope-cli, keytool-cli, seedtool-cli, and jq. We suggest spinning up a cloud Debian server for clean setup. The following instructions assume that setup.

For a more exhaustive and better described look at these processes, see Learning Bitcoin from the Command Line Chapter 10.

Installing Bitcoin

Our Learning Bitcoin Course suggests a number of methods for setting up Bitcoin. We suggest using our Bitcoin Standup script on a Debian system as described in Learning Bitcoin §2.1.

A listing of alternative options is available in Learning Bitcoin §2.2.

Installing Seedtool & Envelope

envelope-cli and seedtool-cli are both available as Rust crates.

If you do not have Rust installed, you’ll need to do so. The following installation instructions work on a Debian system:

sudo apt-get install build-essential
curl https://sh.rustup.rs -sSf | sh
. "$HOME/.cargo/env"

Afterward, you can easily install the crates:

cargo install seedtool-cli
cargo install bc-envelope-cli

Installing Keytool

Keytool is the most challenging installation because it requires setting up a Python environment, compiling, and installing.

The following will install Python on a Debian system:

sudo apt-get install llvm clang lsb-release wget git apt-transport-https pkg-config autoconf libtool libc++-dev libc++abi-dev python3 python3-setuptools
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
sudo ln -s /usr/bin/python3 /usr/bin/python

This will them compile and install:

cd ~
git clone https://github.com/BlockchainCommons/keytool-cli.git
cd keytool-cli/
autoreconf -i
export CC="clang" && export CXX="clang++" && ./build.sh
sudo make install

Installing JQ

JQ is a parsing tool available from jqlang.org. On A Debian system, you can install it with:

sudo apt-get install jq

Exporting a Secret from Bitcoin

1. Understand the Descriptor

bitcoin-cli listdescriptors true | jq -r '.descriptors[].desc'

A descriptor is the standard interoperable methodology for Bitcoin Core.

2. Extract Descriptors

DESCS=$(bitcoin-cli listdescriptors true | jq -r '.descriptors[].desc')
DESC_ARRAY=($DESCS)
for ((i = 0; i < 8; i++)); do
   echo "$i: ${DESC_ARRAY[$i]}"; 
done

3. Extract Private Key

MP_KEY=$(echo ${DESC_ARRAY[0]} | awk -F"[()]" '{print $2}' | awk -F"/" '{print $1}')
echo $MP_KEY

We’re exporting both descriptors and the private key to show two different ways to backup Bitcoin Core.

4a. Store Master Key

KEY_ENVELOPE=$(envelope subject type string "$MP_KEY")
KEY_ENVELOPE=$(envelope assertion add pred-obj known 'isA' known 'MasterKey' "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj string "createdBy" string "`bitcoin-cli --version | head -1`" "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj string "usedBy" string "`bitcoin-cli --version | head -1`" "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj known 'DerivationPath' string "m/44h/0h/0h" "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj known 'DerivationPath' string "m/84h/0h/0h" "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj known 'DerivationPath' string "m/49h/0h/0h" "$KEY_ENVELOPE")
KEY_ENVELOPE=$(envelope assertion add pred-obj known 'DerivationPath' string "m/86h/0h/0h" "$KEY_ENVELOPE")

envelope format $KEY_ENVELOPE

This is a fairly minimal set of metadata. Best practice would also typically add a ‘date’ and a ‘note’. The object is to have sufficient information to make use of the seed when it’s recovered in the future.

4b. Store Descriptors

DESC_ENVELOPE_1=$(envelope subject type string "descriptors-for-bitcoin")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'isA' string "collectionOfDescriptors" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj string "createdBy" string "`bitcoin-cli --version | head -1`" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj string "usedBy" string "`bitcoin-cli --version | head -1`" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[0]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[1]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[2]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[3]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[4]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[5]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[6]}" "$DESC_ENVELOPE_1")
DESC_ENVELOPE_1=$(envelope assertion add pred-obj known 'OutputDescriptor' string "${DESC_ARRAY[7]}" "$DESC_ENVELOPE_1")

envelope format $DESC_ENVELOPE_1

These descriptors are stored as raw text. Blockchain Commons also has a BCR laying out how to store a descrpitor in a more standardized UR format.

5. Shard Envelope

KEY_SHARES=$(envelope sskr split --group "2-of-3" $KEY_ENVELOPE)
KEY_ARRAY=($KEY_SHARES)

An SSKR Envelope creates a new secret, encrypts the envelope with it, and just shards just that secret.

6a. Check Your Work

echo ${KEY_ARRAY[0]}
echo ${KEY_ARRAY[1]}
echo ${KEY_ARRAY[2]}

6b. Check Your Work

RESTORED_KEY=$(envelope sskr join "${KEY_ARRAY[0]}" "${KEY_ARRAY[1]}")
envelope format $RESTORED_KEY

Best practice would be to verify each pair of shares reconstructs the envelope.

Importing a Secret into Bitcoin Core

1. Create a Seed

SEED=$(seedtool)
echo $SEED

2. Create a Fingerprint

FINGERPRINT=$(keytool --seed $SEED master-key-fingerprint)
echo $FINGERPRINT

The fingerprint isn’t technically necessary to create a descriptor, but it’s metadata that reminds you where a descriptor came from.

3. Create Account Key

AKEY=$(keytool --seed $SEED --account-derivation-path "m/84h/0h/0h" account-key-base58)
echo $AKEY

We choose to create an account key rather than a master key to full the least & necessary design philosophy.

4. Create Descriptor

DESC="wpkh([$FINGERPRINT/84h/0h/0h]$AKEY/0/*)"
DESC_CS=$(bitcoin-cli getdescriptorinfo $DESC | jq -r '.checksum')
DESC_WITH_CS=$DESC#$DESC_CS
echo $DESC_WITH_CS

Obviously, you need to know what a descriptor should look like. listdescriptors is a great guide but BIP-380 is the ultimate source.

A checksum is required by Bitcoin Core to work with descriptors.

5. Import Descriptor

bitcoin-cli -named createwallet wallet_name="seedtool" blank=true
bitcoin-cli -rpcwallet=seedtool importdescriptors '''[{ "desc": "'$DESC_WITH_CS'", "timestamp":1780329126, "active": true, "range": [0,100] }]'''

6. Check Your Work

bitcoin-cli listdescriptors

7a. Backup with Seedtool

seedtool -i hex $SEED -o bip39
seedtool -i hex $SEED -o sskr --groups 2-of-3 --sskr-format ur

Seedtool can do Shamir’s Secret Sharing on its own, as shown here, but it’s better to put the seed into an envelope and add metadata before sharding.

7b. Test Your Backup

echo "ur:sskr/gosgtyaeadaegylnahsomsfxstamonssdwotasynuofxoybdnshd ur:sskr/gosgtyaeadaocavdihwplnpkfwiodnpfkgzodtmkidkssbndhgwl" | seedtool -i sskr

8a. Backup with Envelope

SEED_ENVELOPE=$(envelope subject type string "$SEED")
SEED_ENVELOPE=$(envelope assertion add pred-obj known 'isA' known 'Seed' "$SEED_ENVELOPE")
envelope format $SEED_ENVELOPE

8b. Add Metadata to Seed

SEED_ENVELOPE=$(envelope assertion add pred-obj string "createdBy" string "`seedtool -V`" "$SEED_ENVELOPE")
SEED_ENVELOPE=$(envelope assertion add pred-obj string "usedBy" string "`bitcoin-cli --version | head -1`" "$SEED_ENVELOPE")
SEED_ENVELOPE=$(envelope assertion add pred-obj known 'DerivationPath' string "m/84h/0h/0h" "$SEED_ENVELOPE")
envelope format $SEED_ENVELOPE

This is a fairly minimal set of metadata. Best practice would also typically add a ‘date’ and a ‘note’. The object is to have sufficient information to make use of the seed when it’s recovered in the future.

8c. Shard Seed

SEED_SHARES=$(envelope sskr split --group "2-of-3" $SEED_ENVELOPE)
SEED_ARRAY=($SEED_SHARES)
echo ${SEED_ARRAY[0]}