diff --git a/setup.py b/setup.py
index 73909e8..7cd1458 100644
--- a/setup.py
+++ b/setup.py
@@ -15,7 +15,7 @@
         'submit50': [('**.py', 'python', None),],
     },
     description="This is submit50, with which you can submit solutions to problems for CS50.",
-    install_requires=["lib50>=2,<3", "requests>=2.19", "termcolor>=1.1"],
+    install_requires=["lib50>=3,<4", "requests>=2.19", "termcolor>=1.1"],
     keywords=["submit", "submit50"],
     name="submit50",
     python_requires=">=3.6",
@@ -25,6 +25,6 @@
     entry_points={
         "console_scripts": ["submit50=submit50.__main__:main"]
     },
-    version="3.0.4",
+    version="3.1.0",
     include_package_data=True
 )
diff --git a/submit50/__main__.py b/submit50/__main__.py
index 2d4defb..a98d5bb 100644
--- a/submit50/__main__.py
+++ b/submit50/__main__.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
-import os
 import argparse
+import enum
 import gettext
 import logging
 import pkg_resources
@@ -21,6 +21,29 @@
 
 SUBMIT_URL = "https://submit.cs50.io"
 
+class LogLevel(enum.IntEnum):
+    DEBUG = logging.DEBUG
+    INFO = logging.INFO
+    WARNING = logging.WARNING
+    ERROR = logging.ERROR
+
+
+class ColoredFormatter(logging.Formatter):
+    COLORS = {
+        "ERROR": "red",
+        "WARNING": "yellow",
+        "DEBUG": "cyan",
+        "INFO": "magenta",
+    }
+
+    def __init__(self, fmt, use_color=True):
+        super().__init__(fmt=fmt)
+        self.use_color = use_color
+
+    def format(self, record):
+        msg = super().format(record)
+        return msg if not self.use_color else termcolor.colored(msg, getattr(record, "color", self.COLORS.get(record.levelname)))
+
 
 class Error(Exception):
     pass
@@ -50,6 +73,30 @@ def check_version():
                      "Please upgrade."))
 
 
+def setup_logging(level):
+    """
+    Sets up logging for lib50.
+    level 'info' logs all git commands run to stderr
+    level 'debug' logs all git commands and their output to stderr
+    """
+    logger = logging.getLogger("lib50")
+
+    # Set verbosity level on the lib50 logger
+    logger.setLevel(level.upper())
+
+    handler = logging.StreamHandler(sys.stderr)
+    handler.setFormatter(ColoredFormatter("(%(levelname)s) %(message)s", use_color=sys.stderr.isatty()))
+
+    # Direct all logs to sys.stderr
+    logger.addHandler(handler)
+
+    # Don't animate the progressbar if LogLevel is either info or debug
+    lib50.ProgressBar.DISABLED = logger.level < LogLevel.WARNING
+
+    # Show exceptions when debugging
+    excepthook.verbose = logger.level == LogLevel.DEBUG
+
+
 def cprint(text="", color=None, on_color=None, attrs=None, **kwargs):
     """Colorizes text (and wraps to terminal's width)."""
     # Assume 80 in case not running in a terminal
@@ -62,7 +109,7 @@ def cprint(text="", color=None, on_color=None, attrs=None, **kwargs):
                      color=color, on_color=on_color, attrs=attrs, **kwargs)
 
 
-def prompt(included, excluded):
+def prompt(honesty, included, excluded):
     if included:
         cprint(_("Files that will be submitted:"), "green")
         for file in included:
@@ -76,16 +123,33 @@ def prompt(included, excluded):
         for other in excluded:
             cprint("./{}".format(other), "yellow")
 
+    # If there's no honesty question, continue.
+    if not honesty:
+        return True
+    
     # Prompt for honesty
     try:
-        answer = input(_("Keeping in mind the course's policy on academic honesty, "
-                         "are you sure you want to submit these files (yes/no)? "))
+        # Show default message
+        if honesty == True:
+            honesty_question = _(
+                "Keeping in mind the course's policy on academic honesty, "
+                "are you sure you want to submit these files (yes/no)? "
+            )
+        # If a custom message is configured, show that instead
+        else:
+            honesty_question = str(honesty)
+        
+        # Get the user's answer
+        answer = input(honesty_question)
     except EOFError:
         answer = None
         print()
+    
+    # If no answer given, or yes is not given, don't continue
     if not answer or not re.match(f"^\s*(?:{_('y|yes')})\s*$", answer, re.I):
         return False
-
+    
+    # Otherwise, do continue
     return True
 
 
@@ -102,9 +166,9 @@ def excepthook(type, value, tb):
 
     cprint(_("Submission cancelled."), "red")
 
-
 excepthook.verbose = True
 
+
 class LogoutAction(argparse.Action):
     def __init__(self, option_strings, dest=argparse.SUPPRESS, default=argparse.SUPPRESS, help=_("logout of submit50")):
         super().__init__(option_strings, dest=dest, nargs=0, default=default, help=help)
@@ -124,20 +188,29 @@ def main():
 
     parser = argparse.ArgumentParser(prog="submit50")
     parser.add_argument("--logout", action=LogoutAction)
-    parser.add_argument("-v", "--verbose",
-                        action="store_true",
-                        help=_("show commands being executed"))
-    parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
-    parser.add_argument("slug", help=_(
-        "prescribed identifier of work to submit"))
+    parser.add_argument(
+        "--log-level",
+        action="store",
+        default="warning",
+        choices=[level.name.lower() for level in LogLevel],
+        type=str.lower,
+        help=_('warning: displays usage warnings.'
+                '\ninfo: adds all commands run.'
+                '\ndebug: adds the output of all commands run.')
+    )
+    parser.add_argument(
+        "-V", "--version", 
+        action="version", 
+        version=f"%(prog)s {__version__}"
+    )
+    parser.add_argument(
+        "slug", 
+        help=_("prescribed identifier of work to submit")
+    )
 
     args = parser.parse_args()
 
-    excepthook.verbose = args.verbose
-    if args.verbose:
-        logging.basicConfig(level=os.environ.get("SUBMIT50_LOGLEVEL", "INFO"))
-        # Disable progress bar so it doesn't interfere with log
-        lib50.ProgressBar.DISABLED = True
+    setup_logging(args.log_level)
 
     check_announcements()
     check_version()