diff --git a/bin/votar.js b/bin/votar.js
new file mode 100755
index 0000000000000000000000000000000000000000..3ab2900596525b60bf2eae2a55b0af538b98f7c4
--- /dev/null
+++ b/bin/votar.js
@@ -0,0 +1,112 @@
+#!/usr/bin/node
+
+"use strict"
+
+const   Libbfa      =   require( process.env.BFAHOME + '/bin/libbfa.js');
+const   rl          =   require('readline').createInterface(
+        { input: process.stdin, output: process.stdout }
+    );
+var     child       =   require( "child_process" );
+var     web3;
+var     bfa;
+
+function    init()
+{
+    bfa             =   new Libbfa();
+    web3            =   bfa.newweb3();
+    mainmenu();
+}
+
+function    mainmenu()
+{
+    console.log(
+        "Type \"new\" to create a new contract, or type the address of an\n"
+        + " existing contract. An address must start with \"0x\"."
+    );
+    rl.question(
+        "new/address: ",
+        (answer) => {
+            if ( answer.toLowerCase() == "new" )
+                deployNew();
+            else
+            if ( bfa.isAddr(answer) )
+                useExisting( answer );
+            else
+                bfa.fatal( "I have no idea what to do with \""+answer+"\"." );
+            rl.close;
+        }
+    );
+}
+
+function    deployNew()
+{
+    var     ballot      =   bfa.deploy
+    var     ballotsrc   =   bfa.home + "/src/" + "Ballot.sol";
+    var     jsonstr     =   child.execFileSync(
+        "solc", [ "--optimize", "--combined-json", "abi,bin", ballotsrc ]
+    )
+    .toString();
+    var     json        =   JSON.parse( jsonstr );
+    if ( json == undefined )
+        fatal( "I can not read that json: " + jsonstr );
+console.log( json.contract.keys );
+    var     name        =   json.contracts.keys[0];
+    var     abi         =   json.contracts.name.abi;
+    var     bin         =   json.contracts.name.bin;
+    var     contract    =   new web3.eth.Contract(
+        abi,
+        {
+            from:           bfa.account,
+            gas:            4000000,
+            data:           "0x"+bin
+        }
+    );
+    contract.deploy(
+        {   
+            arguments:      [
+                "Vote for Trump?",
+                [
+                    "Yes",
+                    "No"
+                ]
+            ]
+        }
+    )
+    .send()
+    .then(
+        function(newContractInstance)
+        {
+            var addr    =   newContractInstance.options.address;
+            bfa.fs.writeFileSync( bfa.networkdir + "/contracts/" + addr + "/abi", abi );
+            bfa.fs.writeFileSync( bfa.networkdir + "/contracts/" + addr + "/bin", bin );
+            useExisting( addr );
+        }
+    );
+}
+
+function    useExiting( nameaddr )
+{
+    var     ballot      =   bfa.contract( web3, nameaddr );
+    if ( undefined == ballot )
+        fatal( 'Can not initialise Ballot contact. Did you remember to import it first?' );
+    // showballot -- show contract details
+    var     isChairman  =   bfa.account == ballot.ballotChairman;
+    var     you         =   ballot.ballotChairman;
+    if ( isChairman )
+        you             =   "You";
+    var     now         =   Math.floor( Date.now() / 1000 );
+    var     starts      =   new Date( Date.setTime( ballot.ballotVoteStarts * 1000 ));
+    var     ends        =   new Date( Date.setTime( ballot.ballotVoteBefore * 1000 ));
+    console.log( "Title        : " + ballot.ballotTitle );
+    console.log( "Chairman     : " + you );
+    console.log( "Voting starts: " + starts.getDate() );
+    console.log( "Vote before  : " + ends  .getDate() );
+    console.log( "[etcetc]" );
+    console.log( "Current results are: [blabla]" );
+    if ( isChairman && starts < now )
+        console.log( "You are the chairman of this ballot and can register allowed voters." );
+    if ( now >= starts && now < ends )
+        console.log( "You should try to vote." );
+}
+
+init();