added repl to wskdb
diff --git a/nodejs/client/lib/repl.js b/nodejs/client/lib/repl.js
new file mode 100644
index 0000000..06a3b82
--- /dev/null
+++ b/nodejs/client/lib/repl.js
@@ -0,0 +1,89 @@
+var prompt = require('inquirer'),
+    rewriter = require('./rewriter');
+
+var help = {
+    handler: function help() {
+	console.log('The available commands are:');
+	console.log();
+
+	var grouped = {};
+	for (var x in commandHandlers) {
+	    var already = grouped[commandHandlers[x].description];
+	    if (already) {
+		grouped[commandHandlers[x].description] = already + ", " + x;
+	    } else {
+		grouped[commandHandlers[x].description] = x;
+	    }
+	}
+	
+	var pruned = [];
+	for (var d in grouped) {
+	    pruned.push({ command: grouped[d], description: d });
+	}
+
+	console.log(columnify(pruned, { minWidth: 18 }));
+    },
+    description: "Print this help text"
+};
+var attach = {
+    handler: rewriter.attach,
+    description: "Attach to an action",
+    synchronous: true
+};
+var detach = {
+    handler: rewriter.detach,
+    description: "Detatch from an action",
+    synchronous: true
+};
+var exit = {
+    handler: function(wskprops) {
+	//console.log("Cleaning up".red);
+	rewriter.detachAll(wskprops, process.exit);
+    },
+    description: "Quit the debugger"
+};
+var invoke = {
+    handler: rewriter.invoke,
+    description: "Invoke an action",
+    synchronous: true
+};
+
+var commandHandlers = {
+    invoke: invoke,
+    attach: attach,
+    detach: detach,
+    exit: exit,
+    quit: exit,
+    e: exit,
+    q: exit,
+    help: help,
+    h: help,
+    '?': help
+};
+
+function repl(wskprops) {
+    prompt.prompt([{
+	name: 'command', message: '(wskdb)',
+	validate: function(line) {
+	    var commandLine = line.split(/\s+/);
+	    return commandLine.length > 0 && commandHandlers[commandLine[0]] ? true : "Invalid command";
+	}
+    }]).then(function(response) {
+	var commandLine = response.command.split(/\s+/);
+	var command = commandLine.shift();
+	var handler = commandHandlers[command];
+
+	if (handler.synchronous) {
+	    commandLine.unshift(repl.bind(undefined, wskprops));
+	}
+	commandLine.unshift(wskprops);
+
+	handler.handler.apply(undefined, commandLine);
+
+	if (!handler.synchronous) {
+	    repl(wskprops);
+	}
+    });
+}
+
+exports.repl = repl;
diff --git a/nodejs/client/lib/rewriter.js b/nodejs/client/lib/rewriter.js
new file mode 100644
index 0000000..c2d5603
--- /dev/null
+++ b/nodejs/client/lib/rewriter.js
@@ -0,0 +1,182 @@
+var uuid = require('uuid'),
+    openwhisk = require('openwhisk'),
+    api = {
+	host: 'https://openwhisk.ng.bluemix.net',
+	path: '/api/v1'
+    };
+
+var attached = {};
+
+var echoCompletion = "function main(params) { return params; }";
+
+function setupOpenWhisk(wskprops) {
+    var key = wskprops['AUTH'];
+    var namespace = wskprops['NAMESPACE'];
+    var ow = openwhisk({
+	api: api.host + api.path,
+	api_key: key,
+	namespace: namespace
+    });
+    return ow;
+}
+
+exports.attach = function attach(wskprops, next, entity) {
+    var names = attached[entity] = {
+	triggerName: uuid.v4(),
+	actionName: uuid.v4(),
+	ruleName: uuid.v4(),
+	action: echoCompletion
+    };
+
+    console.log("Attaching".blue + " to " + entity);
+
+    var ow = setupOpenWhisk(wskprops);
+
+    try {
+	Promise.all([ow.triggers.create(names),
+		     ow.actions.create(names)])
+	    .then(function() {
+		ow.rules
+		    .create({ ruleName: names.ruleName, trigger: names.triggerName, action: names.actionName })
+		    .then(next);
+	    });
+    } catch (e) {
+	console.error(e);
+    }
+};
+
+exports.detachAll = function detachAll(wskprops, next) {
+    var ow = setupOpenWhisk(wskprops);
+
+    var count = 0;
+    function done() {
+	if (--count <= 0) {
+	    next && next();
+	}
+    }
+    
+    for (var entity in attached) {
+	count++;
+    }
+
+    if (count == 0) {
+	done();
+    } else {
+	for (var entity in attached) {
+	    exports.detach(wskprops, done, entity);
+	}
+    }
+};
+
+exports.detach = function detach(wskprops, next, entity) {
+    console.log("Detaching".blue + " from " + entity);
+
+    function errlog(idx, noNext) {
+	return function(err) {
+	    console.error("Error " + idx, err);
+	    if (!noNext) next();
+	};
+    }
+    
+    var names = attached[entity];
+    if (names) {
+	try {
+	    var ow = setupOpenWhisk(wskprops);
+	    //console.log("D1");
+	    ow.rules.disable(names).then(function() {
+		try {
+		    //console.log("D2");
+		    Promise.all([ow.triggers.delete(names),
+				 ow.actions.delete(names)])
+			.then(function(values) {
+			    //console.log("D3");
+			    ow.rules.delete(names).then(function() {
+				try { delete attached[entity]; next(); } catch (err) { errlog(5, true)(); }
+			    }, errlog(4));
+			}, errlog(3));
+		} catch (err) { errlog(2, true)(); }
+	    }, errlog(1));
+	} catch (e) {
+	    console.error(e);
+	}
+    }
+};
+
+exports.invoke = function invoke() {
+    try {
+	exports._invoke.apply(undefined, arguments);
+    } catch (e) {
+	console.error(e);
+    }
+};
+exports._invoke = function invoke() {
+    var args = Array.prototype.slice.call(arguments);
+    var wskprops = args.shift();
+    var namespace = wskprops['NAMESPACE'];
+    var next = args.shift();
+    var action = args.shift();
+
+    var params = {};
+    for (var i = 0; i < args.length; i++) {
+	if (args[i] == '-p') {
+	    params[args[++i]] = args[++i];
+	}
+    }
+
+    var invokeThisAction, waitForThisAction;
+    
+    var attachedTo = attached[action];
+    if (!attachedTo) {
+	invokeThisAction = action;
+	waitForThisAction = action;
+
+    } else {
+	invokeThisAction = 'owdbg/invoker';
+
+	params.action = action;
+	params.namespace = namespace;
+
+	params.onDone_trigger = attachedTo.triggerName;
+	waitForThisAction = attachedTo.actionName;
+    }
+
+    //console.log("PARAMS", invokeThisAction, params);
+
+    var key = wskprops['AUTH'];
+    var ow = setupOpenWhisk(wskprops);
+    var owForActivations = openwhisk({
+	api: api.host + api.path,
+	api_key: key,
+	namespace: '_'
+    });
+
+    ow.actions.invoke({
+	actionName: invokeThisAction,
+	params: params
+    }).then(function(activation) {
+	if (activation && activation.activationId) {
+	    // successfully invoked
+	    if (!attachedTo) {
+		console.log('Successfully invoked with activationId', activation.activationId);
+	    } else {
+
+	    }
+
+	    var timer = setInterval(function waitForResponse() {
+		owForActivations.activations.list({ limit: 10 }).then(function(list) {
+		    for (var i = 0; i < list.length; i++) {
+			var activation = list[i];
+			if (activation.name == waitForThisAction) {
+			    clearInterval(timer);
+			    owForActivations.activations.get({ activation: activation.activationId }).then(function(activation) {
+				console.log(JSON.stringify(activation, undefined, 4));
+				next();
+			    });
+			    break;
+			}
+		    }
+		});
+	    }, 2000);
+	}
+    });
+}
diff --git a/nodejs/client/package.json b/nodejs/client/package.json
index 9fb35e1..4bf8747 100644
--- a/nodejs/client/package.json
+++ b/nodejs/client/package.json
@@ -10,11 +10,12 @@
   "license": "ISC",
   "dependencies": {
     "colors": "^1.1.2",
+    "columnify": "^1.5.4",
     "expand-home-dir": "0.0.3",
+    "inquirer": "^1.1.3",
     "node-inspector": "^0.12.8",
     "open": "0.0.5",
     "openwhisk": "^2.1.3",
-    "prompt": "^1.0.0",
     "properties-parser": "^0.3.1",
     "request": "^2.75.0",
     "tmp": "0.0.29",
diff --git a/nodejs/client/wskdb.js b/nodejs/client/wskdb.js
index 7ae6fe2..c99ea27 100644
--- a/nodejs/client/wskdb.js
+++ b/nodejs/client/wskdb.js
@@ -2,10 +2,10 @@
     tmp = require('tmp'),
     open = require('open'),
     path = require('path'),
+    repl = require('./lib/repl').repl,
     spawn = require('child_process').spawn,
     colors = require('colors'),
-    prompt = require('prompt'),
-    openwhisk = require('openwhisk'),
+    columnify = require('columnify'),
     WebSocket = require('ws'),
     expandHomeDir = require('expand-home-dir'),
     propertiesParser = require('properties-parser'),
@@ -23,13 +23,23 @@
 var ws = new WebSocket(broker.host + broker.path);
 
 ws.on('open', function open() {
-    console.log('The wskdb client is ready to debug!');
+    console.log('Welcome to the OpenWhisk Debugger');
+    console.log();
 
-    var key = propertiesParser.read(expandHomeDir('~/.wskprops'))['AUTH'];
+    var wskprops = propertiesParser.read(expandHomeDir('~/.wskprops'));
+    var key = wskprops['AUTH'];
     ws.send(JSON.stringify({
 	type: 'init',
 	key: key
     }));
+
+    var keepAlive = setInterval(function poke() {
+	ws.send(JSON.stringify({
+	    type: 'keep-alive'
+	}));
+    }, 5000);
+
+    repl(wskprops);
 });
 
 ws.on('close', function() {
@@ -50,17 +60,9 @@
 	    console.log('Debug session requested');
 	    //console.log(JSON.stringify(message, undefined, 4));
 
-	    var keepAlive = setInterval(function poke() {
-		ws.send(JSON.stringify({
-		    type: 'keep-alive'
-		}));
-	    }, 5000);
-	    
 	    function done(err, result) {
 		console.log('Finishing up this debug session');
 
-		clearInterval(keepAlive);
-
 		ws.send(JSON.stringify({
 		    type: err ? 'circuit-breaker' : 'end',
 		    key: message.key,
@@ -98,7 +100,6 @@
 });
 
 function debugDebug(message, ws, done) {
-    prompt.start();
     prompt.get({
 	name: 'result', description: 'Return value',
 	conform: function(result) {
@@ -198,9 +199,14 @@
 */
 
 process.on('exit', function onExit() {
-    ws.send(JSON.stringify({
-	type: 'disconnect'
-    }, function ack() {
-	ws.close();
-    }));
+    try {
+	console.log("Goodbye!".red);
+
+	ws.send(JSON.stringify({
+	    type: 'disconnect'
+	}, function ack() {
+	    ws.close();
+	}));
+    } catch (e) {
+    }
 });
diff --git a/nodejs/client/wskinvoke.sh b/nodejs/client/wskinvoke.sh
index 0af255b..eb990f5 100755
--- a/nodejs/client/wskinvoke.sh
+++ b/nodejs/client/wskinvoke.sh
@@ -24,8 +24,6 @@
 wsk action create ${ACTION} lib/echo.js >& /dev/null
 wsk rule create ${RULE} ${TRIGGER} ${ACTION} >& /dev/null
 
-wait
-
 wsk action invoke owdbg/invoker -p namespace "${NAMESPACE}" -p onDone_trigger ${TRIGGER} -p action $@
 
 echo -n "Your debugging session should now be active."