diff --git a/bin/unlock.js b/bin/unlock.js
new file mode 100755
index 0000000000000000000000000000000000000000..66cf79dacbf3d69dff23a2d061f39697661a61bc
--- /dev/null
+++ b/bin/unlock.js
@@ -0,0 +1,115 @@
+#!/usr/bin/node
+
+const   Libbfa      =   require( process.env.BFAHOME + '/bin/libbfa.js');
+const	bfa	    =   new Libbfa();
+const   rl          =   require('readline').createInterface(
+        { input: process.stdin, output: process.stdout }
+    );
+var	web3        =   bfa.newweb3();
+// First time we try to unlock, we will use this empty passphrase.
+var     passphrase  =   "";
+
+function atLeastOneFailedSoGetNewPass(x)
+{
+    if ( !process.stdin.isTTY )
+        bye( 0, "Stdin is not a tty. Will not try with other passwords." );
+    rl.question(
+        "Enter another password to try: ",
+        (answer) => {
+            passphrase = answer;
+            if ( answer == "" )
+                bye( 0, "Bye." );
+            unlockall();
+        }
+    );
+}
+
+function bye( exitcode, msg )
+{
+    console.log( msg );
+    rl.close();
+    process.exit( exitcode );
+}
+
+function pluralEnglish( num, single, plural )
+{
+    if ( num == 1 )
+        return single;
+    return plural;
+}
+
+function unlockall()
+{
+    var     wallets             =   new Array();
+    web3.eth.personal.bfalistWallets()
+    .then(
+        function pushone(x)
+        {
+            var     failures    =   0;
+            var     promises    =   new Array();
+            var     i           =   x.length;
+            while ( i-- > 0 )
+                if ( x[i].status == "Locked" )
+                    wallets.push( x[i] );
+            i                   =   wallets.length;
+            if ( i == 0 )
+                bye( 0, "List of accounts to unlock is empty." );
+            while ( i-- > 0 )
+            {
+                var     j       =   wallets[i].accounts.length;
+                while ( j-- > 0 )
+                {
+                    var addr    =   wallets[i].accounts[j].address;
+                    //console.log( "Trying to unlock " + addr + "." );
+                    var promise =   
+                        web3.eth.personal.unlockAccount( addr, passphrase, 0 )
+                        .catch(
+                            error =>
+                            {
+                                failures++;
+                                return error;
+                            }
+                        );
+                    promises.push( promise );
+                }
+            }
+            var     empty       =   "";
+            if ( passphrase == "" )
+                empty           =   " with an empty passphrase";
+            console.log(
+                "Attempting to unlock "
+                + promises.length
+                + " account" + pluralEnglish(promises.length,"","s")
+                + empty + "."
+            );
+            Promise.all( promises )
+            .then(
+                function(x)
+                {
+                    if ( failures == 0 )
+                        bye( 0, "OK." );
+                    console.log( failures + " account" + pluralEnglish(failures," is","s are") + " still locked." );
+                    atLeastOneFailedSoGetNewPass();
+                },
+                function(x)
+                {
+                    console.log( x );
+                    bye( 1, "I can't imagine this text will ever be shown." );
+                }
+            );
+        },
+        function errWalletList(x)
+        {
+            bye( 1, x );
+        }
+    )
+}
+
+web3.eth .personal.extend({
+    methods: [{
+        name:   'bfalistWallets',
+        call:   'personal_listWallets',
+        params: 0
+    }]
+});
+unlockall();