This branch looks very good Matthew, thank you for this work and for investigating this ssh stuff! I wrote a lot of comments, but many of them are just nice to have/minors/do-whit-them-what-you-want. LGTM with (possible) changes. QA ok with some comments (about the initial agent check and the SIGINT handling). https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py File quickstart/app.py (right): https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode98 quickstart/app.py:98: utils.start_ssh_agent() It seems an OSError raised from this call would crash the application. Also, this always starts the agent, even if the user has one already running. Do we have a way to avoid that? This could also be tackled in another card. https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode108 quickstart/app.py:108: 'keys yourself [s], or cancel [C]? ') Maybe ^C here too? https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode114 quickstart/app.py:114: raise ProgramExit('If you would like to create the keys yourself, ' This is displayed as an error, but I am not sure this is an error. sys.exit(msg) could be used instead. https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode120 quickstart/app.py:120: def check_ssh_keys(): Very nice commented function, thank you. https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode124 quickstart/app.py:124: in some way. Raise OSError (via utils.start_ssh_agent) if we couldn't I don't see the start_ssh_agent call here. Is this still true? https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode131 quickstart/app.py:131: retcode, output, error = utils.call('/usr/bin/ssh-add', '-l') error does not seem to be used here and can be safely replaced with _ https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode150 quickstart/app.py:150: raise ProgramExit(msg.format(error).encode('utf-8')) You can avoid encoding ProgramExit messages . https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode164 quickstart/app.py:164: while not check_ssh_keys(): ^C produces a traceback. It's not that important, but we can easily avoid it with something like: try: while not check_ssh_keys(): print('.', end='') sys.stdout.flush() time.sleep(3) except KeyboardInterrupt: sys.exit('\nquitting') https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode166 quickstart/app.py:166: sys.stdout.flush() Interesting, why is this required? A comment would be nice. https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode185 quickstart/app.py:185: if retcode > 0: Is it ok if retcode is < 0? Can this happen? If not, we can just check "if retcode:". https://codereview.appspot.com/39610049/diff/40001/quickstart/app.py#newcode188 quickstart/app.py:188: if retcode > 0: Same as above. https://codereview.appspot.com/39610049/diff/40001/quickstart/tests/test_app.py File quickstart/tests/test_app.py (right): https://codereview.appspot.com/39610049/diff/40001/quickstart/tests/test_app.py#newcode240 quickstart/tests/test_app.py:240: class TestCheckSSHKeys( Nice tests! https://codereview.appspot.com/39610049/