nunchuk-coldcard-hsm
Nunchuk Coldcard HSM
If the user is creating a wallet, also use nunchuk-wallet-creation.
If the user wants to create a wallet with Coldcard or add a Coldcard key, ask whether they want plain Coldcard signing or HSM mode before other Coldcard-specific setup questions, unless they already mentioned HSM.
Requires ckcc on PATH.
Install ckcc:
pip install 'ckcc-protocol[cli]'
Use Coldcard with Nunchuk
Progress:
- Export the descriptor with
ckcc xpub -v. - Add the key to the wallet with
nunchuk sandbox add-key --descriptor. - Create the wallet and export the descriptor to a file.
- Enroll it on the Coldcard with
ckcc upload <descriptor-file> --miniscript. - Sign a transaction with
nunchuk tx get --wallet <wallet-id> --tx-id <txid> --json | jq -r .psbt > <txid.psbt>,ckcc sign --base64 <txid.psbt>, andnunchuk tx sign --psbt <signed-psbt-base64>.
Export a mainnet account descriptor:
ckcc xpub -v "m/48'/0'/0'/2'"
nunchuk sandbox add-key <sandbox-id> --slot 0 --descriptor "[xfp/48h/0h/0h/2h]xpub..."
Export a testnet account descriptor:
ckcc xpub -v "m/48'/1'/0'/2'"
nunchuk sandbox add-key <sandbox-id> --slot 0 --descriptor "[xfp/48h/1h/0h/2h]tpub..."
If you are not sure which network the Coldcard is using:
ckcc chain
Get fingerprint and xpub separately if needed:
ckcc xfp
ckcc xpub "m/48'/1'/0'/2'"
Enroll an exported wallet descriptor:
nunchuk wallet export <wallet-id> --type descriptor > wallet.txt
ckcc upload wallet.txt --miniscript
For MK3 classic multisig config only:
nunchuk wallet export <wallet-id> --type multisig-config > wallet.txt
ckcc upload wallet.txt --multisig
List registered miniscript wallet names:
ckcc miniscript ls
Inspect one registered miniscript wallet:
ckcc miniscript get <wallet-name>
Use Coldcard in HSM Mode
HSM Mode is the Coldcard feature for signing transactions without a person physically present. It is an advanced setup that requires extra software and a policy.json file. Not supported on COLDCARD Q.
Read these references as needed:
- Read
references/coldcard-hsm-rules.mdwhen creating or reviewingpolicy.jsonrules and top-level policy settings. - Read
references/coldcard-hsm-local-codes.mdwhen the policy useslocal_conf. - Read
references/coldcard-hsm-security.mdbefore enablingboot_to_hsm,priv_over_ux, or other unattended-signing security settings.
Progress:
- Create, finalize, and enroll the wallet on Coldcard.
- Do not treat the step above as completion for an HSM request.
- Ask whether the user wants unrestricted signing or a custom policy.
- Use unrestricted signing by default if the user does not ask for spending limits, whitelists, local confirmation, or HSM users.
- Create HSM users only if the policy requires user authorization.
- Validate
policy.jsonwithckcc hsm-start -n policy.json. - Start HSM Mode with
ckcc hsm-start. - Confirm the active policy on the Coldcard screen.
- Check status with
ckcc hsm. - Authorize transactions with
ckcc auth <user>for TOTP orckcc auth <user> -pfor password if the active policy requires user authorization. - Sign transactions with
ckcc sign --base64 <tx.psbt>so the result can be passed tonunchuk tx sign --psbt.
Unrestricted policy.json:
{
"never_log": true,
"rules": [
{}
]
}
Example limited policy.json:
{
"notes": "Office wallet policy",
"never_log": true,
"period": 1440,
"rules": [
{
"max_amount": 1000000,
"per_period": 5000000
}
]
}
This example allows up to 0.01 BTC per transaction and 0.05 BTC per 24 hours.
For a custom policy, read references/coldcard-hsm-rules.md first.
HSM users
For TOTP, the usual flow is to scan the QR shown on the Coldcard with any RFC6238-compatible authentication app, such as FreeOTP (https://freeotp.github.io/) or Google Authenticator. Use --show-qr if you want the QR contents locally instead.
Create a TOTP user:
ckcc user alice
Create a password user with a Coldcard-generated password:
ckcc user alice --pass
Create a password user with a password you enter:
ckcc user alice --ask-pass
Create a password user non-interactively:
ckcc user alice --text-secret "my-secret-password"
Authorize a TOTP user for HSM signing:
ckcc auth alice 123456
Authorize a password user for HSM signing:
ckcc auth alice "my-secret-password" --psbt-file tx.psbt
Delete a user:
ckcc user alice --delete
Start HSM mode
Validate a policy file first:
ckcc hsm-start -n policy.json
Start HSM mode:
# Confirm on the Coldcard screen.
ckcc hsm-start policy.json
Check current HSM status:
ckcc hsm
Defaults
- Prefer
ckcc xpub -vbecause it prints[xfp/path]xpubin a form you can paste intonunchuk sandbox add-key --descriptor. - Use unrestricted signing (
never_log: true,rules: [{}]) by default unless the user asks for custom constraints. - Use
ckcc hsm-start -nbefore uploading a new policy file. - Create HSM users only before activating a policy that references them.
Gotchas
- If the Coldcard network is wrong, the exported path and
xpubortpubprefix will not match the wallet network. Checkckcc chainif you are unsure. - Default to
ckcc upload <descriptor-file> --miniscriptfor exported descriptors. Use--multisigonly for MK3 classic multisig config files. - For signing, enroll the wallet on the Coldcard before entering HSM Mode. If the wallet is unknown, Coldcard may try to import it from the PSBT, but HSM Mode blocks that path with
MS enroll not allowed in HSM mode. - Run
ckcc authwhen the active HSM rule requires user authorization. For password users, the approval is tied to the exact PSBT file. For the current PSBT, approvals can be queued before signing. ckcc hsm-startneeds approval on the Coldcard screen.ckcc hsmshows only a summary of the active policy.- Use
ckcc sign --base64for Nunchuk import; without it,ckcc signwrites binary PSBT output. - If
ckcc signfails withOSError: read errorand no SD card is inserted, set"never_log": trueinpolicy.json. - Removing a user can invalidate a policy that refers to that user.
- Read
references/coldcard-hsm-rules.mdbefore editing or reviewing a Coldcard HSM policy file. - If
policy.jsonneeds a wallet name for a miniscript wallet, enroll first and useckcc miniscript lsto find the registered wallet name. - Read
references/coldcard-hsm-local-codes.mdbefore usinglocal_conf. - Read
references/coldcard-hsm-security.mdbefore usingboot_to_hsmorpriv_over_ux.
More from nunchuk-io/agent-skills
nunchuk-setup
Install Nunchuk CLI, authenticate, switch between mainnet and testnet, change Electrum server, and inspect saved config. Use when a command needs login, network, or Electrum setup, or when the user asks to check current auth or config.
12nunchuk-wallet-creation
Create Nunchuk Bitcoin wallets, add keys, and finalize them. Use when the user wants to create a wallet.
12nunchuk-wallet-management
Inspect and manage existing Nunchuk wallets, including balances, receive addresses, backup/export, recovery, rename, delete, and dummy-transaction approval. Use when the user wants to work with a wallet that has already been created.
12nunchuk-wallet-transactions
Create, sign, inspect, list, and broadcast Bitcoin transactions. Use when the user wants to send funds, sign a transaction, broadcast it, or inspect wallet transaction history.
12nunchuk-invitations
Send, review, accept, and deny Nunchuk wallet invitations during wallet setup. Use when the user wants to invite others, check whether they were invited, or respond to an invitation.
11nunchuk-platform-key
Enable, inspect, disable, and update Nunchuk Platform key policies for wallets. Use when the user asks about Platform key, spending limits, signing delay, auto-broadcast, or policy updates.
11