diff --git a/docs/bitcoin-core-usage.md b/docs/bitcoin-core-usage.md
index 364aa2217..6a0ad219d 100644
--- a/docs/bitcoin-core-usage.md
+++ b/docs/bitcoin-core-usage.md
@@ -1,37 +1,58 @@
 # Using Coldcard with Bitcoin Core
 
-## Background
+As of Bitcoin Core v0.19.0+ the setup can be done fully airgapped, but spending
+needs a USB connection and additional software such as [HWI](https://github.com/bitcoin-core/HWI).
 
-Core has not always supported BIP32 hierarchical keys, and it does not presently
-support BIP44 derivation. Instead it uses derivation like this:
+## Setup Steps
 
-    m/0'/{change}'/{index}'
+### Bitcoin Core v0.19.0+
 
-It will also, as of 0.16, do Segwit in P2SH by default. In time, `bech32` will
-become the default address format.
+For compatibility with other wallet software we use the BIP84 address derivation
+(m/84'/0'/{account}'/{change}/{index}) and native SegWit (bech32) addresses. It's
+recommended to set `addresstype=bech32` in [bitcoin.conf](https://github.com/bitcoin/bitcoin/blob/9546a785953b7f61a3a50e2175283cbf30bc2151/doc/bitcoin-conf.md).
 
-## Setup Steps
+First, generate a new seed phrase on the Coldcard. Then create a watch-only wallet
+in Bitcoin Core: File -> Create Wallet. Give it a name, and ensure "Disable Private Keys"
+is selected.
 
-- generate a new seed phrase on the Coldcard
-- export the xpub file from Coldcard (USB or MicroSD)
-- import that xpub as a new wallet in core
-- display balances
+The public keys can exported via an SD card, or via USB.
 
-## Day-to-day Operation
+To export via SD card:
 
-- generate unsigned transactions
-- get that onto the Coldcard, and sign it there
-- use core to broadcast the new txn for confirmation
+- go to Advanced -> MicroSD card -> Bitcoin Core
+- on your computer open public.txt, copy the `importmulti` command
+- in Bitcoin Core, go to Windows -> Console
+- select Coldcard in the wallet dropdown
+- paste the `importmulti` command. It should respond with a success message
+
+To export via USB:
+
+- install HWI and follow the [instructions for Setup](https://github.com/bitcoin-core/HWI/blob/master/docs/bitcoin-core-usage.md#setup)
+- during the `getkeypool` command, the use of `--wpkh` ensures compatibility with BIP84,
+as long as you only use bech32 (native SegWit) addresses.
 
-## Use of "dumpwallet" command
+If you've used this wallet before, Bitcoin Core needs to rescan the blockchain to
+show your balance and earlier transactions. Use the RPC command `rescanblockchain HEIGHT`
+where `HEIGHT` is an old enough block (0 if you don't know).
 
-- You can do a "dumpwallet" command and get the `xprv` associated with your
-wallet. We can import that, and then you'd need to destroy the existing wallet
-files, backups of those, and so on.
+### Bitcoin Core v0.18.0
 
-- Our output file, called `public.txt`, can be compared to dumpwallet's output, but:
-    - you must find the section with appropriate derivation path for core
-    - core puts the addresses into a random order, not sequential like ours
-    - segwit, and p2sh segwit choice has to match
+The same steps as Bitcoin Core v0.19.0, except that the wallet must be created
+using the RPC (console window in the GUI):
 
+```
+createwallet Coldcard true
+```
+
+## Day-to-day Operation
+
+### Bitcoin Core v0.18.0+
+
+See HWI [instructions for usage](https://github.com/bitcoin-core/HWI/blob/master/docs/bitcoin-core-usage.md#usage).
+
+- generate unsigned transactions
+- get that onto the Coldcard, and sign it there
+- use core to broadcast the new txn for confirmation
 
+When using the Bitcoin Core GUI (Graphical User Interface), avoid using P2SH wrapped receive
+addresses, as this will cause incompatibility with other wallets.
diff --git a/shared/actions.py b/shared/actions.py
index 8d5c955b7..a010e9238 100644
--- a/shared/actions.py
+++ b/shared/actions.py
@@ -726,6 +726,24 @@ async def electrum_skeleton(*a):
 
     return MenuSystem(rv)
 
+async def bitcoin_core_skeleton(*A):
+    # save output descriptors into a file
+    # - user has no choice, it's going to be bech32 with  m/84'/{coin_type}'/0' path
+    import chains
+
+    ch = chains.current_chain()
+
+    if await ux_show_story('''\
+This saves a command onto the MicroSD card that includes the public keys.\
+You can then run that command in Bitcoin Core without ever connecting this Coldcard to a computer.\
+''' + SENSITIVE_NOT_SECRET) != 'y':
+        return
+
+    # no choices to be made, just do it.
+    with imported('backups') as bk:
+        await bk.make_bitcoin_core_wallet()
+
+
 async def electrum_skeleton_step2(_1, _2, item):
     # pick a semi-random file name, render and save it.
     with imported('backups') as bk:
diff --git a/shared/backups.py b/shared/backups.py
index c0c8ad929..938ce9680 100644
--- a/shared/backups.py
+++ b/shared/backups.py
@@ -527,21 +527,13 @@ def generate_public_contents():
             yield fp.getvalue()
             del fp
 
-async def make_summary_file(fname_pattern='public.txt'):
-    # record **public** values and helpful data into a text file
+# total_parts does need not be precise
+async def write_text_file(fname_pattern, body, title, total_parts=72):
     from main import dis, pa, settings
     from files import CardSlot, CardMissingError
     from actions import needs_microsd
 
-    dis.fullscreen('Generating...')
-
-    # generator function:
-    body = generate_public_contents()
-
-    total_parts = 72        # need not be precise
-
     # choose a filename
-        
     try:
         with CardSlot() as card:
             fname, nice = card.pick_filename(fname_pattern)
@@ -559,9 +551,92 @@ async def make_summary_file(fname_pattern='public.txt'):
         await ux_show_story('Failed to write!\n\n\n'+str(e))
         return
 
-    msg = '''Summary file written:\n\n%s''' % nice
+    msg = '''%s file written:\n\n%s''' % (title, nice)
     await ux_show_story(msg)
 
+async def make_summary_file(fname_pattern='public.txt'):
+    from main import dis
+
+    # record **public** values and helpful data into a text file
+    dis.fullscreen('Generating...')
+
+    # generator function:
+    body = generate_public_contents()
+
+    await write_text_file(fname_pattern, body, 'Summary')
+
+async def make_bitcoin_core_wallet(fname_pattern='bitcoin-core.txt'):
+    from main import dis, settings
+    import ustruct
+    xfp = b2a_hex(ustruct.pack('<I', settings.get('xfp'))).decode().lower()
+
+    dis.fullscreen('Generating...')
+
+    # generator function:
+    payload = ujson.dumps(generate_bitcoin_core_wallet())
+
+    body = '''\
+# Bitcoin Core Wallet Import File
+
+https://github.com/Coldcard/firmware/blob/master/docs/bitcoin-core-usage.md
+
+## For wallet with master key fingerprint: {xfp}
+
+Wallet operates on blockchain: {nb}
+
+## IMPORTANT WARNING
+
+Do **not** deposit to any address in this file unless you have a working
+wallet system that is ready to handle the funds at that address!
+
+## Bitcoin Core RPC
+
+The following command can be entered after opening Window -> Console in Bitcoin Core,
+or using bitcoin-cli:
+
+importmulti '{payload}'
+
+'''.format(payload=payload, xfp=xfp, nb=chains.current_chain().name)
+
+    await write_text_file(fname_pattern, body, 'Bitcoin Core')
+
+def generate_bitcoin_core_wallet():
+    # Generate the data for an RPC command to import keys into Bitcoin Core
+    from descriptor import AddChecksum
+    from main import settings
+    import ustruct
+
+    from public_constants import AF_P2WPKH
+
+    chain = chains.current_chain()
+    assert chain.ctype in {'BTC', 'XTN'}, "Only Bitcoin supported"
+
+    derive = "m/84'/{coin_type}'/{account}'".format(account=0, coin_type=chain.b44_cointype)
+
+    with stash.SensitiveValues() as sv:
+        xpub = chain.serialize_public(sv.derive_path(derive))
+
+    xfp = settings.get('xfp')
+    txt_xfp = b2a_hex(ustruct.pack('<I', xfp)).decode().lower()
+
+    chain = chains.current_chain()
+
+    _,vers,_ = version.get_mpy_version()
+
+    return list(map(lambda internal: {
+        'desc': AddChecksum("wpkh([{fingerprint}/84h/{coin_type}h/{account}h]{xpub}/{change}/*)".format(
+            fingerprint=txt_xfp,
+            coin_type=chain.b44_cointype,
+            account=0,
+            xpub=xpub,
+            change=1 if internal else 0
+        )),
+        'range': [0, 1000],
+        'timestamp': 'now',
+        'internal': internal,
+        'keypool': True,
+        'watchonly': True
+    }, [False, True]))
 
 def generate_wasabi_wallet():
     # Generate the data for a JSON file which Wasabi can open directly as a new wallet.
diff --git a/shared/chains.py b/shared/chains.py
index ceac38a19..492363163 100644
--- a/shared/chains.py
+++ b/shared/chains.py
@@ -10,7 +10,7 @@
 from ucollections import namedtuple
 from opcodes import OP_CHECKMULTISIG
 
-# See SLIP 132 <https://github.com/satoshilabs/slips/blob/master/slip-0132.md> 
+# See SLIP 132 <https://github.com/satoshilabs/slips/blob/master/slip-0132.md>
 # for background on these version bytes. Not to be confused with SLIP-32 which involves Bech32.
 Slip132Version = namedtuple('Slip132Version', ('pub', 'priv', 'hint'))
 
@@ -249,15 +249,12 @@ def current_chain():
 # see bip49 for meaning of the meta vars
 CommonDerivations = [
     # name, path.format(), addr format
-    ( '{core_name}', "m/{account}'/{change}'/{idx}'", AF_CLASSIC ),
-    ( '{core_name} (Segregated Witness, P2PKH)',
-                "m/{account}'/{change}'/{idx}'", AF_P2WPKH ),
     ( 'Electrum (not BIP44)', "m/{change}/{idx}", AF_CLASSIC ),
     ( 'BIP44 / Electrum', "m/44'/{coin_type}'/{account}'/{change}/{idx}", AF_CLASSIC ),
     ( 'BIP49 (P2WPKH-nested-in-P2SH)', "m/49'/{coin_type}'/{account}'/{change}/{idx}",
             AF_P2WPKH_P2SH ),   # generates 3xxx/2xxx p2sh-looking addresses
 
-    ( 'BIP84 (Native Segwit P2PKH)', "m/84'/{coin_type}'/{account}'/{change}/{idx}",
+    ( 'BIP84 (Native Segwit P2WPKH)', "m/84'/{coin_type}'/{account}'/{change}/{idx}",
             AF_P2WPKH ),           # generates bc1 bech32 addresses
 ]
 
diff --git a/shared/descriptor.py b/shared/descriptor.py
new file mode 100644
index 000000000..c059ed403
--- /dev/null
+++ b/shared/descriptor.py
@@ -0,0 +1,48 @@
+# From: https://github.com/bitcoin/bitcoin/blob/master/src/script/descriptor.cpp
+
+def PolyMod(c, val):
+    c0 = c >> 35
+    c = ((c & 0x7ffffffff) << 5) ^ val
+    if (c0 & 1):
+        c ^= 0xf5dee51989
+    if (c0 & 2):
+        c ^= 0xa9fdca3312
+    if (c0 & 4):
+        c ^= 0x1bab10e32d
+    if (c0 & 8):
+        c ^= 0x3706b1677a
+    if (c0 & 16):
+        c ^= 0x644d626ffd
+    return c
+
+def DescriptorChecksum(desc):
+    INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "
+    CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+    c = 1
+    cls = 0
+    clscount = 0
+    for ch in desc:
+        pos = INPUT_CHARSET.find(ch)
+        if pos == -1:
+            return ""
+        c = PolyMod(c, pos & 31)
+        cls = cls * 3 + (pos >> 5)
+        clscount += 1
+        if clscount == 3:
+            c = PolyMod(c, cls)
+            cls = 0
+            clscount = 0
+    if clscount > 0:
+        c = PolyMod(c, cls)
+    for j in range(0, 8):
+        c = PolyMod(c, 0)
+    c ^= 1
+
+    ret = [None] * 8
+    for j in range(0, 8):
+        ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31]
+    return ''.join(ret)
+
+def AddChecksum(desc):
+    return desc + "#" + DescriptorChecksum(desc)
diff --git a/shared/flow.py b/shared/flow.py
index f7458ef60..f7c5b1f6b 100644
--- a/shared/flow.py
+++ b/shared/flow.py
@@ -59,6 +59,7 @@ async def which_pin_menu(_1,_2, item):
     MenuItem("Backup System", f=backup_everything),
     MenuItem("Dump Summary", f=dump_summary),
     MenuItem('Upgrade From SD', f=microsd_upgrade),
+    MenuItem("Bitcoin Core", f=bitcoin_core_skeleton),
     MenuItem("Electrum Wallet", f=electrum_skeleton),
     MenuItem("Wasabi Wallet", f=wasabi_skeleton),
     MenuItem('List Files', f=list_files),
