       msg.reply cmds.join "\n"
 
   robot.respond /tf create key$/i, (msg) ->
-    unless robot.auth.isAdmin(msg.envelope.user) or robot.auth.hasRole(msg.envelope.user,'tf')
-      return msg.send {room: msg.message.user.name}, "Not authorized.  Missing 'tf' role."
+    unless robot.auth.isAdmin(msg.envelope.user) or robot.auth.hasRole(msg.envelope.user,tfRole)
+      return msg.send {room: msg.message.user.name}, "Not authorized.  Missing #{tfRole} role."
 
     if fs.existsSync("#{publickey}")
       return msg.send {room: msg.message.user.name}, "Key exists!  Destroy it first."

        msg.send {room: msg.message.user.name}, "stdout:\n```\n#{stdout}\n```"

  robot.respond /tf list(\sprojects)?$/i, (msg) ->
    unless robot.auth.isAdmin(msg.envelope.user) or robot.auth.hasRole(msg.envelope.user,'tf')
      return msg.send {room: msg.message.user.name}, "Not authorized.  Missing 'tf' role."

    dir = []
    for fn in fs.readdirSync(basepath)
      stat = fs.statSync("#{basepath}/#{fn}")
      dir.push fn if stat.isDirectory()

    msg.reply dir.join "\n"

    return msg.send {room: msg.message.user.name}, "Key destroyed!"

  robot.respond /tf clone ([^\s]+) ([^\s]+)$/i, (msg) ->
    unless robot.auth.isAdmin(msg.envelope.user) or robot.auth.hasRole(msg.envelope.user,tfRole)
      return msg.send {room: msg.message.user.name}, "Not authorized.  Missing #{tfRole} role."

    url = msg.match[1]
    projname = msg.match[2].replace /\//, "_"
