From a8d0eab2c6168d44fff29a38305bbdbe35959b83 Mon Sep 17 00:00:00 2001
From: dthree <threedeecee@gmail.com>
Date: Mon, 22 Feb 2016 08:37:08 -0800
Subject: [PATCH] init

---
 .babelrc                                       |   3 +
 .eslintignore                                  |   1 +
 .gitignore                                     |  31 +
 .istanbul.yml                                  |  55 ++
 .travis.yml                                    |   9 +
 LICENSE                                        |  22 +
 README.md                                      | 193 +++++++
 appveyor.yml                                   |  21 +
 bin/alias.js                                   |   2 +
 bin/cash.js                                    |   7 +
 bin/cat.js                                     |   2 +
 bin/cd.js                                      |   2 +
 bin/cp.js                                      |   2 +
 bin/echo.js                                    |   2 +
 bin/grep.js                                    |   2 +
 bin/kill.js                                    |   2 +
 bin/less.js                                    |   2 +
 bin/ls.js                                      |   2 +
 bin/mkdir.js                                   |   2 +
 bin/mv.js                                      |   2 +
 bin/parser.js                                  |  50 ++
 bin/pwd.js                                     |   2 +
 bin/rm.js                                      |   2 +
 bin/sort.js                                    |   2 +
 bin/touch.js                                   |   2 +
 bin/unalias.js                                 |   2 +
 commands.json                                  | 171 ++++++
 dist/commands/alias.js                         | 109 ++++
 dist/commands/boilerplate.js                   |  98 ++++
 dist/commands/cat.js                           | 116 ++++
 dist/commands/cd.js                            |  55 ++
 dist/commands/cp.js                            | 207 +++++++
 dist/commands/echo.js                          |  78 +++
 dist/commands/grep.js                          |   3 +
 dist/commands/kill.js                          |  97 ++++
 dist/commands/less.js                          |   3 +
 dist/commands/ls.js                            | 353 ++++++++++++
 dist/commands/mkdir.js                         |  86 +++
 dist/commands/mv.js                            | 105 ++++
 dist/commands/pwd.js                           |  28 +
 dist/commands/rm.js                            | 171 ++++++
 dist/commands/sort.js                          | 269 +++++++++
 dist/commands/touch.js                         | 151 +++++
 dist/commands/unalias.js                       | 100 ++++
 dist/delimiter.js                              |  33 ++
 dist/help.js                                   |  35 ++
 dist/help/alias.js                             |   3 +
 dist/help/cat.js                               |   3 +
 dist/help/cd.js                                |   3 +
 dist/help/cp.js                                |   3 +
 dist/help/echo.js                              |   3 +
 dist/help/grep.js                              |   3 +
 dist/help/kill.js                              |   3 +
 dist/help/ls.js                                |   3 +
 dist/help/mkdir.js                             |   3 +
 dist/help/mv.js                                |   3 +
 dist/help/pwd.js                               |   3 +
 dist/help/rm.js                                |   3 +
 dist/help/sort.js                              |   3 +
 dist/help/touch.js                             |   3 +
 dist/help/unalias.js                           |   3 +
 dist/index.js                                  | 185 ++++++
 dist/lib/sugar.js                              | 747 +++++++++++++++++++++++++
 dist/util/colorFile.js                         |  34 ++
 dist/util/columnify.js                         |  58 ++
 dist/util/converter.date.js                    |  30 +
 dist/util/converter.path.js                    |  19 +
 dist/util/converter.permissions.js             |  39 ++
 dist/util/expand.js                            |  29 +
 dist/util/fetch.js                             |  50 ++
 dist/util/fileFromPath.js                      |  17 +
 dist/util/intercept.js                         |  47 ++
 dist/util/interfacer.js                        |  45 ++
 dist/util/lpad.js                              |  20 +
 dist/util/pad.js                               |  22 +
 dist/util/stripAnsi.js                         |  14 +
 dist/util/unlinkSync.js                        |  30 +
 dist/util/walkDir.js                           |  41 ++
 dist/util/walkDirRecursive.js                  |  24 +
 dist/windows.js                                | 120 ++++
 gulpfile.js                                    | 127 +++++
 package.json                                   | 103 ++++
 packages/cat/README.md                         |  47 ++
 packages/cat/bin/cat.js                        |   2 +
 packages/cat/bin/parser.js                     |  50 ++
 packages/cat/dist/commands/cat.js              | 116 ++++
 packages/cat/dist/help/cat.js                  |   3 +
 packages/cat/dist/util/expand.js               |  29 +
 packages/cat/dist/util/fetch.js                |  50 ++
 packages/cat/dist/util/interfacer.js           |  45 ++
 packages/cat/dist/util/lpad.js                 |  20 +
 packages/cat/dist/util/stripAnsi.js            |  14 +
 packages/cat/package.json                      |  51 ++
 packages/cp/README.md                          |  47 ++
 packages/cp/bin/cp.js                          |   2 +
 packages/cp/bin/parser.js                      |  50 ++
 packages/cp/dist/commands/cp.js                | 207 +++++++
 packages/cp/dist/help/cp.js                    |   3 +
 packages/cp/dist/util/expand.js                |  29 +
 packages/cp/dist/util/interfacer.js            |  45 ++
 packages/cp/package.json                       |  51 ++
 packages/kill/README.md                        |  47 ++
 packages/kill/bin/kill.js                      |   2 +
 packages/kill/bin/parser.js                    |  50 ++
 packages/kill/dist/commands/kill.js            |  97 ++++
 packages/kill/dist/help/kill.js                |   3 +
 packages/kill/dist/util/interfacer.js          |  45 ++
 packages/kill/package.json                     |  50 ++
 packages/ls/README.md                          |  47 ++
 packages/ls/bin/ls.js                          |   2 +
 packages/ls/bin/parser.js                      |  50 ++
 packages/ls/dist/commands/ls.js                | 353 ++++++++++++
 packages/ls/dist/help/ls.js                    |   3 +
 packages/ls/dist/util/colorFile.js             |  34 ++
 packages/ls/dist/util/columnify.js             |  58 ++
 packages/ls/dist/util/converter.date.js        |  30 +
 packages/ls/dist/util/converter.permissions.js |  39 ++
 packages/ls/dist/util/fileFromPath.js          |  17 +
 packages/ls/dist/util/interfacer.js            |  45 ++
 packages/ls/dist/util/lpad.js                  |  20 +
 packages/ls/dist/util/pad.js                   |  22 +
 packages/ls/dist/util/stripAnsi.js             |  14 +
 packages/ls/dist/util/walkDir.js               |  41 ++
 packages/ls/dist/util/walkDirRecursive.js      |  24 +
 packages/ls/package.json                       |  52 ++
 packages/mkdir/README.md                       |  47 ++
 packages/mkdir/bin/mkdir.js                    |   2 +
 packages/mkdir/bin/parser.js                   |  50 ++
 packages/mkdir/dist/commands/mkdir.js          |  86 +++
 packages/mkdir/dist/help/mkdir.js              |   3 +
 packages/mkdir/dist/util/interfacer.js         |  45 ++
 packages/mkdir/package.json                    |  49 ++
 packages/mv/README.md                          |  47 ++
 packages/mv/bin/mv.js                          |   2 +
 packages/mv/bin/parser.js                      |  50 ++
 packages/mv/dist/commands/mv.js                | 105 ++++
 packages/mv/dist/help/mv.js                    |   3 +
 packages/mv/dist/util/expand.js                |  29 +
 packages/mv/dist/util/interfacer.js            |  45 ++
 packages/mv/package.json                       |  51 ++
 packages/pwd/README.md                         |  47 ++
 packages/pwd/bin/parser.js                     |  50 ++
 packages/pwd/bin/pwd.js                        |   2 +
 packages/pwd/dist/commands/pwd.js              |  28 +
 packages/pwd/dist/help/pwd.js                  |   3 +
 packages/pwd/dist/util/interfacer.js           |  45 ++
 packages/pwd/package.json                      |  48 ++
 packages/rm/README.md                          |  47 ++
 packages/rm/bin/parser.js                      |  50 ++
 packages/rm/bin/rm.js                          |   2 +
 packages/rm/dist/commands/rm.js                | 171 ++++++
 packages/rm/dist/help/rm.js                    |   3 +
 packages/rm/dist/util/expand.js                |  29 +
 packages/rm/dist/util/interfacer.js            |  45 ++
 packages/rm/dist/util/unlinkSync.js            |  30 +
 packages/rm/package.json                       |  50 ++
 packages/sort/README.md                        |  47 ++
 packages/sort/bin/parser.js                    |  50 ++
 packages/sort/bin/sort.js                      |   2 +
 packages/sort/dist/commands/sort.js            | 269 +++++++++
 packages/sort/dist/help/sort.js                |   3 +
 packages/sort/dist/util/expand.js              |  29 +
 packages/sort/dist/util/fetch.js               |  50 ++
 packages/sort/dist/util/interfacer.js          |  45 ++
 packages/sort/dist/util/stripAnsi.js           |  14 +
 packages/sort/package.json                     |  51 ++
 packages/template.README.md                    |  32 ++
 packages/template.package.json                 |  44 ++
 packages/touch/README.md                       |  47 ++
 packages/touch/bin/parser.js                   |  50 ++
 packages/touch/bin/touch.js                    |   2 +
 packages/touch/dist/commands/touch.js          | 151 +++++
 packages/touch/dist/help/touch.js              |   3 +
 packages/touch/dist/lib/sugar.js               | 747 +++++++++++++++++++++++++
 packages/touch/dist/util/interfacer.js         |  45 ++
 packages/touch/package.json                    |  51 ++
 src/commands/alias.js                          | 113 ++++
 src/commands/boilerplate.js                    | 101 ++++
 src/commands/cat.js                            | 133 +++++
 src/commands/cd.js                             |  60 ++
 src/commands/cp.js                             | 213 +++++++
 src/commands/echo.js                           |  84 +++
 src/commands/grep.js                           |   3 +
 src/commands/kill.js                           | 103 ++++
 src/commands/less.js                           |   3 +
 src/commands/ls.js                             | 376 +++++++++++++
 src/commands/mkdir.js                          |  90 +++
 src/commands/mv.js                             | 108 ++++
 src/commands/pwd.js                            |  30 +
 src/commands/rm.js                             | 179 ++++++
 src/commands/sort.js                           | 279 +++++++++
 src/commands/touch.js                          | 169 ++++++
 src/commands/unalias.js                        |  97 ++++
 src/delimiter.js                               |  35 ++
 src/help.js                                    |  52 ++
 src/help/alias.js                              |  17 +
 src/help/cat.js                                |  24 +
 src/help/cd.js                                 |  10 +
 src/help/cp.js                                 |  16 +
 src/help/echo.js                               |  22 +
 src/help/grep.js                               |  33 ++
 src/help/kill.js                               |  22 +
 src/help/ls.js                                 |  33 ++
 src/help/mkdir.js                              |  11 +
 src/help/mv.js                                 |  18 +
 src/help/pwd.js                                |  14 +
 src/help/rm.js                                 |  22 +
 src/help/sort.js                               |  22 +
 src/help/touch.js                              |  20 +
 src/help/unalias.js                            |  14 +
 src/index.js                                   | 182 ++++++
 src/lib/sugar.js                               |  79 +++
 src/util/colorFile.js                          |  37 ++
 src/util/columnify.js                          |  60 ++
 src/util/converter.date.js                     |  31 +
 src/util/converter.path.js                     |  20 +
 src/util/converter.permissions.js              |  41 ++
 src/util/expand.js                             |  33 ++
 src/util/fetch.js                              |  50 ++
 src/util/fileFromPath.js                       |  17 +
 src/util/intercept.js                          |  47 ++
 src/util/interfacer.js                         |  43 ++
 src/util/lpad.js                               |  20 +
 src/util/pad.js                                |  22 +
 src/util/stripAnsi.js                          |  14 +
 src/util/unlinkSync.js                         |  30 +
 src/util/walkDir.js                            |  41 ++
 src/util/walkDirRecursive.js                   |  24 +
 src/windows.js                                 | 124 ++++
 test/alias.js                                  |  85 +++
 test/cat.js                                    | 127 +++++
 test/cd.js                                     |  51 ++
 test/cp.js                                     | 127 +++++
 test/echo.js                                   |  70 +++
 test/help.js                                   |  23 +
 test/kill.js                                   |  78 +++
 test/ls.js                                     | 171 ++++++
 test/mkdir.js                                  |  94 ++++
 test/mv.js                                     | 125 +++++
 test/pwd.js                                    |  23 +
 test/rm.js                                     |  89 +++
 test/sort.js                                   | 139 +++++
 test/touch.js                                  | 125 +++++
 test/unalias.js                                |  71 +++
 test/util/playground.js                        |   9 +
 test/util/util.js                              |  54 ++
 test/vorpal.js                                 |  30 +
 test/windows.js                                |  11 +
 248 files changed, 14483 insertions(+)
 create mode 100755 .babelrc
 create mode 100755 .eslintignore
 create mode 100755 .gitignore
 create mode 100755 .istanbul.yml
 create mode 100755 .travis.yml
 create mode 100755 LICENSE
 create mode 100755 README.md
 create mode 100755 appveyor.yml
 create mode 100644 bin/alias.js
 create mode 100755 bin/cash.js
 create mode 100644 bin/cat.js
 create mode 100644 bin/cd.js
 create mode 100644 bin/cp.js
 create mode 100644 bin/echo.js
 create mode 100644 bin/grep.js
 create mode 100644 bin/kill.js
 create mode 100644 bin/less.js
 create mode 100644 bin/ls.js
 create mode 100644 bin/mkdir.js
 create mode 100644 bin/mv.js
 create mode 100755 bin/parser.js
 create mode 100644 bin/pwd.js
 create mode 100644 bin/rm.js
 create mode 100644 bin/sort.js
 create mode 100644 bin/touch.js
 create mode 100644 bin/unalias.js
 create mode 100755 commands.json
 create mode 100755 dist/commands/alias.js
 create mode 100755 dist/commands/boilerplate.js
 create mode 100755 dist/commands/cat.js
 create mode 100755 dist/commands/cd.js
 create mode 100755 dist/commands/cp.js
 create mode 100755 dist/commands/echo.js
 create mode 100755 dist/commands/grep.js
 create mode 100755 dist/commands/kill.js
 create mode 100755 dist/commands/less.js
 create mode 100755 dist/commands/ls.js
 create mode 100755 dist/commands/mkdir.js
 create mode 100755 dist/commands/mv.js
 create mode 100755 dist/commands/pwd.js
 create mode 100755 dist/commands/rm.js
 create mode 100755 dist/commands/sort.js
 create mode 100755 dist/commands/touch.js
 create mode 100755 dist/commands/unalias.js
 create mode 100755 dist/delimiter.js
 create mode 100755 dist/help.js
 create mode 100755 dist/help/alias.js
 create mode 100755 dist/help/cat.js
 create mode 100755 dist/help/cd.js
 create mode 100755 dist/help/cp.js
 create mode 100755 dist/help/echo.js
 create mode 100755 dist/help/grep.js
 create mode 100755 dist/help/kill.js
 create mode 100755 dist/help/ls.js
 create mode 100755 dist/help/mkdir.js
 create mode 100755 dist/help/mv.js
 create mode 100755 dist/help/pwd.js
 create mode 100755 dist/help/rm.js
 create mode 100755 dist/help/sort.js
 create mode 100755 dist/help/touch.js
 create mode 100755 dist/help/unalias.js
 create mode 100755 dist/index.js
 create mode 100755 dist/lib/sugar.js
 create mode 100755 dist/util/colorFile.js
 create mode 100755 dist/util/columnify.js
 create mode 100755 dist/util/converter.date.js
 create mode 100755 dist/util/converter.path.js
 create mode 100755 dist/util/converter.permissions.js
 create mode 100755 dist/util/expand.js
 create mode 100755 dist/util/fetch.js
 create mode 100755 dist/util/fileFromPath.js
 create mode 100755 dist/util/intercept.js
 create mode 100755 dist/util/interfacer.js
 create mode 100755 dist/util/lpad.js
 create mode 100755 dist/util/pad.js
 create mode 100755 dist/util/stripAnsi.js
 create mode 100755 dist/util/unlinkSync.js
 create mode 100755 dist/util/walkDir.js
 create mode 100755 dist/util/walkDirRecursive.js
 create mode 100755 dist/windows.js
 create mode 100755 gulpfile.js
 create mode 100755 package.json
 create mode 100755 packages/cat/README.md
 create mode 100644 packages/cat/bin/cat.js
 create mode 100755 packages/cat/bin/parser.js
 create mode 100755 packages/cat/dist/commands/cat.js
 create mode 100755 packages/cat/dist/help/cat.js
 create mode 100755 packages/cat/dist/util/expand.js
 create mode 100755 packages/cat/dist/util/fetch.js
 create mode 100755 packages/cat/dist/util/interfacer.js
 create mode 100755 packages/cat/dist/util/lpad.js
 create mode 100755 packages/cat/dist/util/stripAnsi.js
 create mode 100644 packages/cat/package.json
 create mode 100755 packages/cp/README.md
 create mode 100644 packages/cp/bin/cp.js
 create mode 100755 packages/cp/bin/parser.js
 create mode 100755 packages/cp/dist/commands/cp.js
 create mode 100755 packages/cp/dist/help/cp.js
 create mode 100755 packages/cp/dist/util/expand.js
 create mode 100755 packages/cp/dist/util/interfacer.js
 create mode 100644 packages/cp/package.json
 create mode 100755 packages/kill/README.md
 create mode 100644 packages/kill/bin/kill.js
 create mode 100755 packages/kill/bin/parser.js
 create mode 100755 packages/kill/dist/commands/kill.js
 create mode 100755 packages/kill/dist/help/kill.js
 create mode 100755 packages/kill/dist/util/interfacer.js
 create mode 100644 packages/kill/package.json
 create mode 100755 packages/ls/README.md
 create mode 100644 packages/ls/bin/ls.js
 create mode 100755 packages/ls/bin/parser.js
 create mode 100755 packages/ls/dist/commands/ls.js
 create mode 100755 packages/ls/dist/help/ls.js
 create mode 100755 packages/ls/dist/util/colorFile.js
 create mode 100755 packages/ls/dist/util/columnify.js
 create mode 100755 packages/ls/dist/util/converter.date.js
 create mode 100755 packages/ls/dist/util/converter.permissions.js
 create mode 100755 packages/ls/dist/util/fileFromPath.js
 create mode 100755 packages/ls/dist/util/interfacer.js
 create mode 100755 packages/ls/dist/util/lpad.js
 create mode 100755 packages/ls/dist/util/pad.js
 create mode 100755 packages/ls/dist/util/stripAnsi.js
 create mode 100755 packages/ls/dist/util/walkDir.js
 create mode 100755 packages/ls/dist/util/walkDirRecursive.js
 create mode 100644 packages/ls/package.json
 create mode 100755 packages/mkdir/README.md
 create mode 100644 packages/mkdir/bin/mkdir.js
 create mode 100755 packages/mkdir/bin/parser.js
 create mode 100755 packages/mkdir/dist/commands/mkdir.js
 create mode 100755 packages/mkdir/dist/help/mkdir.js
 create mode 100755 packages/mkdir/dist/util/interfacer.js
 create mode 100644 packages/mkdir/package.json
 create mode 100755 packages/mv/README.md
 create mode 100644 packages/mv/bin/mv.js
 create mode 100755 packages/mv/bin/parser.js
 create mode 100755 packages/mv/dist/commands/mv.js
 create mode 100755 packages/mv/dist/help/mv.js
 create mode 100755 packages/mv/dist/util/expand.js
 create mode 100755 packages/mv/dist/util/interfacer.js
 create mode 100644 packages/mv/package.json
 create mode 100755 packages/pwd/README.md
 create mode 100755 packages/pwd/bin/parser.js
 create mode 100644 packages/pwd/bin/pwd.js
 create mode 100755 packages/pwd/dist/commands/pwd.js
 create mode 100755 packages/pwd/dist/help/pwd.js
 create mode 100755 packages/pwd/dist/util/interfacer.js
 create mode 100644 packages/pwd/package.json
 create mode 100755 packages/rm/README.md
 create mode 100755 packages/rm/bin/parser.js
 create mode 100644 packages/rm/bin/rm.js
 create mode 100755 packages/rm/dist/commands/rm.js
 create mode 100755 packages/rm/dist/help/rm.js
 create mode 100755 packages/rm/dist/util/expand.js
 create mode 100755 packages/rm/dist/util/interfacer.js
 create mode 100755 packages/rm/dist/util/unlinkSync.js
 create mode 100644 packages/rm/package.json
 create mode 100755 packages/sort/README.md
 create mode 100755 packages/sort/bin/parser.js
 create mode 100644 packages/sort/bin/sort.js
 create mode 100755 packages/sort/dist/commands/sort.js
 create mode 100755 packages/sort/dist/help/sort.js
 create mode 100755 packages/sort/dist/util/expand.js
 create mode 100755 packages/sort/dist/util/fetch.js
 create mode 100755 packages/sort/dist/util/interfacer.js
 create mode 100755 packages/sort/dist/util/stripAnsi.js
 create mode 100644 packages/sort/package.json
 create mode 100755 packages/template.README.md
 create mode 100755 packages/template.package.json
 create mode 100755 packages/touch/README.md
 create mode 100755 packages/touch/bin/parser.js
 create mode 100644 packages/touch/bin/touch.js
 create mode 100755 packages/touch/dist/commands/touch.js
 create mode 100755 packages/touch/dist/help/touch.js
 create mode 100755 packages/touch/dist/lib/sugar.js
 create mode 100755 packages/touch/dist/util/interfacer.js
 create mode 100644 packages/touch/package.json
 create mode 100755 src/commands/alias.js
 create mode 100755 src/commands/boilerplate.js
 create mode 100755 src/commands/cat.js
 create mode 100755 src/commands/cd.js
 create mode 100755 src/commands/cp.js
 create mode 100755 src/commands/echo.js
 create mode 100755 src/commands/grep.js
 create mode 100755 src/commands/kill.js
 create mode 100755 src/commands/less.js
 create mode 100755 src/commands/ls.js
 create mode 100755 src/commands/mkdir.js
 create mode 100755 src/commands/mv.js
 create mode 100755 src/commands/pwd.js
 create mode 100755 src/commands/rm.js
 create mode 100755 src/commands/sort.js
 create mode 100755 src/commands/touch.js
 create mode 100755 src/commands/unalias.js
 create mode 100755 src/delimiter.js
 create mode 100755 src/help.js
 create mode 100755 src/help/alias.js
 create mode 100755 src/help/cat.js
 create mode 100755 src/help/cd.js
 create mode 100755 src/help/cp.js
 create mode 100755 src/help/echo.js
 create mode 100755 src/help/grep.js
 create mode 100755 src/help/kill.js
 create mode 100755 src/help/ls.js
 create mode 100755 src/help/mkdir.js
 create mode 100755 src/help/mv.js
 create mode 100755 src/help/pwd.js
 create mode 100755 src/help/rm.js
 create mode 100755 src/help/sort.js
 create mode 100755 src/help/touch.js
 create mode 100755 src/help/unalias.js
 create mode 100755 src/index.js
 create mode 100755 src/lib/sugar.js
 create mode 100755 src/util/colorFile.js
 create mode 100755 src/util/columnify.js
 create mode 100755 src/util/converter.date.js
 create mode 100755 src/util/converter.path.js
 create mode 100755 src/util/converter.permissions.js
 create mode 100755 src/util/expand.js
 create mode 100755 src/util/fetch.js
 create mode 100755 src/util/fileFromPath.js
 create mode 100755 src/util/intercept.js
 create mode 100755 src/util/interfacer.js
 create mode 100755 src/util/lpad.js
 create mode 100755 src/util/pad.js
 create mode 100755 src/util/stripAnsi.js
 create mode 100755 src/util/unlinkSync.js
 create mode 100755 src/util/walkDir.js
 create mode 100755 src/util/walkDirRecursive.js
 create mode 100755 src/windows.js
 create mode 100755 test/alias.js
 create mode 100755 test/cat.js
 create mode 100755 test/cd.js
 create mode 100755 test/cp.js
 create mode 100755 test/echo.js
 create mode 100755 test/help.js
 create mode 100755 test/kill.js
 create mode 100755 test/ls.js
 create mode 100755 test/mkdir.js
 create mode 100755 test/mv.js
 create mode 100755 test/pwd.js
 create mode 100755 test/rm.js
 create mode 100755 test/sort.js
 create mode 100755 test/touch.js
 create mode 100755 test/unalias.js
 create mode 100755 test/util/playground.js
 create mode 100755 test/util/util.js
 create mode 100755 test/vorpal.js
 create mode 100755 test/windows.js

diff --git a/.babelrc b/.babelrc
new file mode 100755
index 0000000..af0f0c3
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+  "presets": ["es2015"]
+}
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100755
index 0000000..36a0f83
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+src/lib/sugar.js
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..9db9343
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,31 @@
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+*sublime*
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+.cmd_history
+.cmd_history/*
+.cmd_history/cmd_historycash
\ No newline at end of file
diff --git a/.istanbul.yml b/.istanbul.yml
new file mode 100755
index 0000000..1de2417
--- /dev/null
+++ b/.istanbul.yml
@@ -0,0 +1,55 @@
+verbose: false
+instrumentation:
+    root: .
+    extensions:
+        - .js
+    default-excludes: true
+    excludes: ['./dist/lib/sugar.js']
+    embed-source: false
+    variable: __coverage__
+    compact: true
+    preserve-comments: false
+    complete-copy: false
+    save-baseline: false
+    baseline-file: ./coverage/coverage-baseline.json
+    include-all-sources: false
+    include-pid: false
+    es-modules: false
+reporting:
+    print: summary
+    reports:
+        - lcov
+    dir: ./coverage
+    watermarks:
+        statements: [50, 80]
+        lines: [50, 80]
+        functions: [50, 80]
+        branches: [50, 80]
+    report-config:
+        clover: {file: clover.xml}
+        cobertura: {file: cobertura-coverage.xml}
+        json: {file: coverage-final.json}
+        json-summary: {file: coverage-summary.json}
+        lcovonly: {file: lcov.info}
+        teamcity: {file: null, blockName: Code Coverage Summary}
+        text: {file: null, maxCols: 0}
+        text-lcov: {file: lcov.info}
+        text-summary: {file: null}
+hooks:
+    hook-run-in-context: false
+    post-require-hook: null
+    handle-sigint: false
+check:
+    global:
+        statements: 0
+        lines: 0
+        branches: 0
+        functions: 0
+        excludes: []
+    each:
+        statements: 0
+        lines: 0
+        branches: 0
+        functions: 0
+        excludes: []
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100755
index 0000000..cb42dbf
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,9 @@
+sudo: false
+language: node_js
+node_js:
+  - "5"
+  - "4"
+after_success: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
+branches:
+  only:
+    - master
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..3ecaf41
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2015 DC <threedeecee@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..23363f3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,193 @@
+<h1 align="center">
+	<img width="312" src="http://i.imgur.com/tKrIdAI.jpg" alt="Cash">
+	<!--<img width="256" src="http://i.imgur.com/oIN1WsM.jpg" alt="Cash">-->
+</h1>
+
+
+> Cross-platform Linux commands in pure ES6
+
+[![Build Status](https://travis-ci.org/vorpaljs/cash.svg)](https://travis-ci.org/vorpaljs/cash/)
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/286om4y0wbxs69fy?svg=true)](https://ci.appveyor.com/project/dthree/cash)
+[![Coverage Status](https://coveralls.io/repos/vorpaljs/cash/badge.svg?branch=master&service=github)](https://coveralls.io/github/vorpaljs/cash?branch=master)
+<a href="https://gitter.im/dthree/cash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge">
+  <img src="https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg" alt="Gitter" />
+</a>
+[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
+
+Cash is a cross-platform implementation of Unix shell commands written in pure ES6. 
+
+*Huh?* Okay - think [Cygwin](https://en.wikipedia.org/wiki/Cygwin), except:
+
+- No DLLs
+- Terminal-agnostic
+- 1/15th of the size
+- No native compiling
+- Just:
+
+```bash
+> npm install cash -g
+> cash
+$
+```
+
+<p align="center">
+  <img src="http://i.giphy.com/xT0BKNwUPFhFj2glry.gif" alt="Cash" />
+</p>
+
+
+### Woah.
+
+Yeah. But it gets better. 
+
+Let's mix some Windows & Unix commands together:
+
+```bash
+$ ipconfig | grep IPv4 | sort
+IPv4 Address. . . . . . . . . . . : 10.10.40.50
+IPv4 Address. . . . . . . . . . . : 192.168.100.11
+$
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Interactive)
+
+
+### But I don't want to type "cash"
+
+No problem. Let's make all commands global on your system:
+
+```bash
+> npm install cash-global -g
+> ls -lah
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Global)
+
+
+### Nice, but I only want certain commands
+
+You're covered!
+
+```bash
+> npm install cash-ls -g
+> npm install cash-grep -g
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Global#installing-individual-commands)
+
+
+### Wow. But I want this programmatically!
+
+Again, you're in business:
+
+```js
+const $ = require('cash');
+const out = $.ls('.', {l: true});
+```
+
+Not terse enough? How about this:
+
+```js
+const out = $('ls -lah');
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Programmatic)
+
+
+### Isn't this impossible to do in Node?
+
+It was, before [Vorpal](https://github.com/dthree/vorpal).
+
+Made with ❤ by [dthree](https://github.com/dthree).
+
+Love it? Cash is brand new! Give it a :star: or a tweet to help spread the word!
+
+
+## Contents
+
+- [Introduction](#introduction)
+- [Supported commands](#supported-commands)
+- [Contributing](#contributing)
+- [FAQ](#faq)
+- [License](#license)
+
+- [Wiki](https://github.com/dthree/cash/wiki)
+
+## Introduction
+
+Cash is a project working on a cross-platform implementation of the most used Unix-based commands in pure Javascript and with no external dependencies.
+
+The goal of Cash is to open up these commands to the massive Javascript community for the first time, and to provide a cleaner, simpler and flexible alternative to applications like Cygwin for those wanting the Linux feel on Windows.
+
+Cash was built with strict attention to nearly exact implementations and excellent test coverage of over 200 unit tests.
+
+
+## Supported commands
+
+The following commands are currently implemented:
+
+- alias
+- cat
+- cd
+- cp
+- echo
+- grep
+- kill
+- less
+- ls
+- mkdir
+- mv
+- pwd
+- rm
+- sort
+- touch
+- unalias
+
+Want more commands?
+
+- [Vote on the next commands](https://github.com/dthree/cash/wiki/Roadmap)
+- [Help spread the word:](http://bit.ly/1LBEJ5s) More knowledge of Cash equals more contributors
+- [Contribute](#contributing)
+
+
+## Contributing
+
+- [Editing commands](contributing.md)
+- [Adding new commands](contributing.md)
+
+I am currently looking for someone with experience in building Windows installers (`.msi`) to bundle Cash and its individual components into a self-contained wrapper. I you would like to help with this, send me a ping.
+
+
+## FAQ
+
+
+#### Why Cash?
+
+In its very essence, Cash replaces the Windows CLI prompt (`>`) with the Unix one (`$`), the dollar symbol. 
+
+Cash was most fitting in this sense: 
+
+> Ask and ye shall receive
+
+```
+> cash
+$
+````
+
+Cash is also a play on the word `bash`, and is actually[\[1\]](https://xkcd.com/906) a recursive acronym for Cash Shell.
+
+Shout out to [@aseemk](https://github.com/aseemk) for donating the name.
+
+
+#### Doesn't Shell.js do this?
+
+No. 
+
+For those who don't know, [Shell.js](https://github.com/shelljs/shelljs) is an awesome Node app that implements Unix shell commands programatically in Javascript. Check it out - really. While Shell.js was tremendously helpful in figuring out how to accomplish Cash, the two do not really conflict.
+
+Shell.js *gives the feel of and approximates* Unix commands in a code environment, but does not aim to precisely implement it. 
+By example, Shell.js' `ls` command supports two arguments and returns an array. Cash supports seventeen arguments and strives to mirror the exact funcionality and output of the POSIX-compliant `ls` command.
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100755
index 0000000..98c0282
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,21 @@
+environment:
+  matrix:
+    - nodejs_version: '5'
+    - nodejs_version: '4'
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - set CI=true
+  - set CASH_APPVEYOR=true
+  - npm install -g npm@latest || (timeout 30 && npm install -g npm@latest)
+  - set PATH=%APPDATA%\npm;%PATH%
+  - npm install || (timeout 30 && npm install)
+matrix:
+  fast_finish: true
+build: off
+version: '{build}'
+shallow_clone: true
+clone_depth: 1
+test_script:
+  - node --version
+  - npm --version
+  - npm run test-win || (timeout 30 && npm run test-win)
\ No newline at end of file
diff --git a/bin/alias.js b/bin/alias.js
new file mode 100644
index 0000000..c6568b5
--- /dev/null
+++ b/bin/alias.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'alias');
diff --git a/bin/cash.js b/bin/cash.js
new file mode 100755
index 0000000..bc242d0
--- /dev/null
+++ b/bin/cash.js
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+'use strict';
+var cash = require('../dist/index');
+var delimiter = require('./../dist/delimiter')
+delimiter.refresh(cash.vorpal, function () {
+  cash.show();
+});
diff --git a/bin/cat.js b/bin/cat.js
new file mode 100644
index 0000000..c82524a
--- /dev/null
+++ b/bin/cat.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cat');
diff --git a/bin/cd.js b/bin/cd.js
new file mode 100644
index 0000000..ca81801
--- /dev/null
+++ b/bin/cd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cd');
diff --git a/bin/cp.js b/bin/cp.js
new file mode 100644
index 0000000..a14fb86
--- /dev/null
+++ b/bin/cp.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cp');
diff --git a/bin/echo.js b/bin/echo.js
new file mode 100644
index 0000000..7b2aeff
--- /dev/null
+++ b/bin/echo.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'echo');
diff --git a/bin/grep.js b/bin/grep.js
new file mode 100644
index 0000000..ea45a22
--- /dev/null
+++ b/bin/grep.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'grep');
diff --git a/bin/kill.js b/bin/kill.js
new file mode 100644
index 0000000..06959b5
--- /dev/null
+++ b/bin/kill.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'kill');
diff --git a/bin/less.js b/bin/less.js
new file mode 100644
index 0000000..767a7db
--- /dev/null
+++ b/bin/less.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'less');
diff --git a/bin/ls.js b/bin/ls.js
new file mode 100644
index 0000000..ae0712e
--- /dev/null
+++ b/bin/ls.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'ls');
diff --git a/bin/mkdir.js b/bin/mkdir.js
new file mode 100644
index 0000000..31f0387
--- /dev/null
+++ b/bin/mkdir.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mkdir');
diff --git a/bin/mv.js b/bin/mv.js
new file mode 100644
index 0000000..298c101
--- /dev/null
+++ b/bin/mv.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mv');
diff --git a/bin/parser.js b/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/bin/pwd.js b/bin/pwd.js
new file mode 100644
index 0000000..367f6e8
--- /dev/null
+++ b/bin/pwd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'pwd');
diff --git a/bin/rm.js b/bin/rm.js
new file mode 100644
index 0000000..0bb6783
--- /dev/null
+++ b/bin/rm.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'rm');
diff --git a/bin/sort.js b/bin/sort.js
new file mode 100644
index 0000000..ec3a025
--- /dev/null
+++ b/bin/sort.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'sort');
diff --git a/bin/touch.js b/bin/touch.js
new file mode 100644
index 0000000..89f8d6e
--- /dev/null
+++ b/bin/touch.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'touch');
diff --git a/bin/unalias.js b/bin/unalias.js
new file mode 100644
index 0000000..e027af5
--- /dev/null
+++ b/bin/unalias.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'unalias');
diff --git a/commands.json b/commands.json
new file mode 100755
index 0000000..1c99c59
--- /dev/null
+++ b/commands.json
@@ -0,0 +1,171 @@
+{
+  "commands": [
+    "alias", 
+    "cd", 
+    "cp", 
+    "echo", 
+    "kill", 
+    "ls", 
+    "mkdir", 
+    "mv", 
+    "pwd", 
+    "sort", 
+    "touch", 
+    "cat", 
+    "less",
+    "grep",
+    "rm",
+    "unalias"
+    ],
+  "globalExclusions": [ 
+    "alias",
+    "cd",
+    "echo",
+    "less",
+    "sort",
+    "unalias"
+  ],
+  "importedCommands": [
+    "less",
+    "grep"
+  ],
+  "windowsCommands": [
+    "attrib",
+    "assoc",
+    "cacls",
+    "chcp",
+    "copy",
+    "del",
+    "dir",
+    "driverquery",
+    "erase",
+    "git",
+    "icacls",
+    "ipconfig",
+    "md",
+    "mklink",
+    "move",
+    "net",
+    "npm",
+    "openfiles",
+    "path",
+    "rd",
+    "recover",
+    "ren",
+    "replace",
+    "robocopy",
+    "route",
+    "sc",
+    "schtasks",
+    "setlocal",
+    "start",
+    "subst",
+    "systeminfo",
+    "tasklist",
+    "taskkill",
+    "tree",
+    "ver",
+    "vol",
+    "xcopy"
+  ],
+  "dependencies": {
+    "./dist/delimiter.js": ["username", "./dist/util/converter.path.js"],
+    "./dist/util/colorFile.js": ["./dist/util/stripAnsi.js"],
+    "./dist/util/columnify.js": ["./dist/util/stripAnsi.js", "./dist/util/pad.js"],
+    "./dist/util/converter.path.js": [],
+    "./dist/util/converter.permissions.js": [],
+    "./dist/util/converter.date.js": [],
+    "./dist/util/expand.js": ["glob"],
+    "./dist/util/fetch.js": ["./dist/util/expand.js"],
+    "./dist/util/fileFromPath.js": [],
+    "./dist/util/interfacer.js": [],
+    "./dist/util/lpad.js": ["./dist/util/stripAnsi.js"],
+    "./dist/util/pad.js": ["./dist/util/stripAnsi.js"],
+    "./dist/util/stripAnsi.js": [],
+    "./dist/util/walkDir.js": [],
+    "./dist/util/walkDirRecursive.js": [],
+    "./dist/util/unlinkSync.js": []
+  },
+  "packages": {
+    "cat": {
+      "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/fetch.js", 
+        "./dist/util/interfacer.js", 
+        "./dist/util/lpad.js", 
+        "./dist/util/stripAnsi.js", 
+        "./dist/util/expand.js"
+      ]
+    },
+    "cp": {
+      "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/expand.js", 
+        "./dist/util/interfacer.js"
+      ]
+    },
+    "kill": {
+      "dependencies": ["fkill", "lodash"],
+      "files": [
+        "./dist/util/interfacer.js"
+      ]
+    },
+    "ls": {
+      "dependencies": ["lodash", "chalk", "filesize", "vorpal-autocomplete-fs"],
+      "files": [
+        "./dist/util/colorFile.js", 
+        "./dist/util/columnify.js", 
+        "./dist/util/converter.date.js",
+        "./dist/util/fileFromPath.js",
+        "./dist/util/interfacer.js",
+        "./dist/util/pad.js",
+        "./dist/util/lpad.js",
+        "./dist/util/converter.permissions.js",
+        "./dist/util/stripAnsi.js",
+        "./dist/util/walkDir.js",
+        "./dist/util/walkDirRecursive.js"
+      ]
+    },
+    "mkdir": {
+      "dependencies": ["vorpal-autocomplete-fs"],
+      "files": ["./dist/util/interfacer.js"]
+    },
+    "mv": {
+      "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/expand.js",
+        "./dist/util/interfacer.js"
+      ]
+    },
+    "pwd": {
+      "dependencies": [],
+      "files": [
+        "./dist/util/interfacer.js"
+      ]
+    },
+    "sort": {
+      "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/fetch.js", 
+        "./dist/util/interfacer.js", 
+        "./dist/util/stripAnsi.js", 
+        "./dist/util/expand.js"
+      ]
+    },
+    "touch": {
+      "dependencies": ["lodash", "fs-extra", "vorpal-autocomplete-fs"],
+      "files": [
+        "./dist/util/interfacer.js", 
+        "./dist/lib/sugar.js"
+      ]
+    },
+    "rm": {
+      "dependencies": ["vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/expand.js", 
+        "./dist/util/interfacer.js", 
+        "./dist/util/unlinkSync.js"
+      ]
+    }
+  }
+}
diff --git a/dist/commands/alias.js b/dist/commands/alias.js
new file mode 100755
index 0000000..5d407d9
--- /dev/null
+++ b/dist/commands/alias.js
@@ -0,0 +1,109 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var alias = {
+  exec: function exec(args, options) {
+    args = args || [];
+    options = options || {};
+    var vorpal = options.vorpal;
+
+    if (!vorpal) {
+      throw new Error('Alias is not programatically supported.');
+    }
+
+    vorpal._aliases = vorpal._aliases || [];
+
+    if (args.length < 1) {
+      options.p = true;
+    }
+
+    if (_.isString(args)) {
+      args = [args];
+    }
+
+    // Parse incoming args. Accept either:
+    // alias foo=bar, or
+    // alias foo 'bar and so on'.
+    var key = args.join(' ');
+    var value = undefined;
+    if (String(key).indexOf('=') > -1) {
+      var parts = String(key).trim().split('=');
+      key = parts[0];
+      value = parts[1] || value;
+    } else {
+      var parts = String(key).trim().split(' ');
+      key = parts.shift();
+      value = parts.join(' ');
+    }
+
+    // Remove wrapped quotes from value.
+    if (value !== undefined) {
+      value = String(value).replace(/^[\"|\']|[\"|\']$/g, '');
+    }
+
+    // Pull list of aliases
+    var all = undefined;
+    try {
+      all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      all = [];
+      vorpal.localStorage.removeItem('aliases');
+    }
+
+    if (options.p) {
+      for (var i = 0; i < all.length; ++i) {
+        var item = vorpal.localStorage.getItem('alias|' + all[i]);
+        if (item !== undefined && item !== null) {
+          this.log('alias ' + all[i] + '=\'' + item + '\'');
+        }
+      }
+    } else {
+      if (value) {
+        vorpal.localStorage.setItem('alias|' + key, value);
+        _.remove(all, function (val) {
+          return val === key;
+        });
+        all.push(key);
+      } else {
+        var item = vorpal.localStorage.getItem('alias|' + key);
+        if (item !== undefined && item !== null) {
+          this.log('alias ' + key + '=\'' + item + '\'');
+        } else {
+          this.log('-cash: alias: ' + key + ': not found');
+        }
+      }
+
+      var aliases = {};
+      for (var i = 0; i < all.length; ++i) {
+        var item = vorpal.localStorage.getItem('alias|' + all[i]);
+        if (item !== undefined && item !== null) {
+          aliases[all[i]] = item;
+        }
+      }
+      vorpal._aliases = aliases;
+    }
+
+    vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return alias;
+  }
+  vorpal.api.alias = alias;
+  vorpal.command('alias [name...]').option('-p', 'print all defined aliases in a reusable format').action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: alias,
+      args: args.name,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/boilerplate.js b/dist/commands/boilerplate.js
new file mode 100755
index 0000000..676c039
--- /dev/null
+++ b/dist/commands/boilerplate.js
@@ -0,0 +1,98 @@
+'use strict';
+
+var interfacer = require('./../util/interfacer');
+
+/**
+ * This is a boilerplate for implementing a new command.
+ * Delete all of these comments / instructions before finishing.
+ */
+
+/**
+ * 0. Replace all instances of `cmdName` with
+ *    the exact name of the command being implemented.
+ */
+
+var cmdName = {
+
+  /**
+   * The cmdName.exec method is exposed by Cash
+   * as the only public interfacer to your command.
+   */
+
+  exec: function exec(args, options) {
+    options = options || {};
+
+    /**
+     * 1. Validate arg input to include every
+     *    possible form of input, such as:
+     *
+     *    a. as a string:
+     *       cash.foo('bar and so on', {option: true});
+     *
+     *    b. as an array:
+     *       cash.foo(['bar', 'and', 'so', 'on'], {option: true});
+     *
+     *    c. as interpeted through Vorpal:
+     *       cash('foo bar and so on --option');
+     */
+
+    /**
+     * 2. For errors, use `this.log` to print the
+     *    error message to the user, and only return
+     *    the error code (1, 2, etc.)
+     *
+     *    if (args.length < 1) {
+     *      this.log('foo: cannot bar: requires at least one file name');
+     *      return 1;
+     *    }
+     */
+
+    /**
+     * 3. For all other stdout to the user, use `this.log`.
+     *    For large jobs that should stream logging a
+     *    bit at a time, use multiple `this.log` statements
+     *    and cash will handle the heavy lifting of piping
+     *    and returning the final assembled output to the
+     *    user in the case of programmatically executed
+     *    commands.
+     */
+
+    /**
+     * 4. When complete with no errors, return 0;
+     *
+     *    return 0;
+     */
+  }
+};
+
+module.exports = function (vorpal) {
+  /**
+   * When do a raw execution of the command
+   * without options, Vorpal is not used. In this
+   * case, the raw command is returned.
+   */
+  if (vorpal === undefined) {
+    return cmdName;
+  }
+  vorpal.api.cmdName = cmdName;
+  /**
+   * Registers the command in Vorpal.
+   * Command strings, options and their
+   * descriptions should exactly emulate
+   * existing commands.
+   */
+  vorpal.command('cmdName [files...]').option('-o, --option', 'option description').action(function (args, callback) {
+    args.options = args.options || {};
+    /**
+     * The interfacer method does a
+     * lot of heavy lifting on interfacing with
+     * the command properly.
+     */
+    return interfacer.call(this, {
+      command: cmdName,
+      args: args.files, // only pass in what you need from Vorpal
+      options: args.options, // split the options into their own arg
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/cat.js b/dist/commands/cat.js
new file mode 100755
index 0000000..ee21984
--- /dev/null
+++ b/dist/commands/cat.js
@@ -0,0 +1,116 @@
+'use strict';
+
+var _ = require('lodash');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var lpad = require('./../util/lpad');
+var strip = require('./../util/stripAnsi');
+
+var cat = {
+  exec: function exec(args, options) {
+    var self = this;
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    // -A handler
+    if (options.showall) {
+      options.shownonprinting = true;
+      options.showends = true;
+      options.showtabs = true;
+    }
+
+    // -e handler
+    if (options.e) {
+      options.shownonprinting = true;
+      options.showends = true;
+    }
+
+    // -t handler
+    if (options.t) {
+      options.shownonprinting = true;
+      options.showtabs = true;
+    }
+
+    var stdout = '';
+    try {
+      var stdin = fetch(args.files, args.stdin, {
+        onDirectory: function onDirectory(name) {
+          return 'cat: ' + name + ': Is a directory';
+        },
+        onInvalidFile: function onInvalidFile(name) {
+          return 'cat: ' + name + ': No such file or directory';
+        }
+      });
+      var ctr = 0;
+      for (var i = 0; i < stdin.length; ++i) {
+        // If -s, squeeze double blank lines to a
+        // single line.
+        if (options.squeezeblank) {
+          stdin[i] = stdin[i].replace(/\n\n\s*\n/g, '\n\n');
+        }
+        if (options.showtabs) {
+          stdin[i] = stdin[i].replace(/\t/g, '^I');
+        }
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        stdin[i] = stdin[i].replace(/\s$/, '');
+        var parts = String(stdin[i]).split('\n');
+        for (var j = 0; j < parts.length; ++j) {
+          var blank = strip(parts[j]).trim() === '';
+          // If -b, number every non-blank line
+          // If -n, number every line
+          var numbered = !blank && options.numbernonblank || options.number && !options.numbernonblank;
+          if (numbered) {
+            ctr++;
+          }
+          var numStr = numbered ? lpad(String(ctr), 6, ' ') + '  ' : '';
+          // If -E, append a $ to each line end.
+          var dollarStr = options.showends ? '$' : '';
+          var line = numStr + parts[j] + dollarStr;
+          self.log(line);
+          stdout += line + '\n';
+        }
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return 1;
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cat;
+  }
+  vorpal.api.cat = cat;
+  vorpal.command('cat [files...]').option('-A, --show-all', 'equivalent to -vET').option('-b, --number-nonblank', 'number nonempty output lines, overrides -n').option('-e', 'equivalent to -vE').option('-E, --show-ends', 'display $ at end of each line').option('-n, --number', 'number all output lines').option('-s, --squeeze-blank', 'suppress repeated empty output lines').option('-t', 'equivalent to -vT').option('-T, --show-tabs', 'display TAB characters as ^I').option('-v, --show-nonprinting', 'use ^ and M- notation, except for LFD and TAB') // this doesn't work yet...
+  .autocomplete(fsAutocomplete()).action(function (args, cb) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: cat,
+      args: args,
+      options: args.options,
+      callback: cb
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/cd.js b/dist/commands/cd.js
new file mode 100755
index 0000000..e02141a
--- /dev/null
+++ b/dist/commands/cd.js
@@ -0,0 +1,55 @@
+'use strict';
+
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var delimiter = require('./../delimiter');
+
+var interfacer = require('./../util/interfacer');
+
+var cd = {
+  exec: function exec(dir, options) {
+    var self = this;
+    var vpl = options.vorpal;
+    options = options || {};
+
+    dir = !dir ? delimiter.getHomeDir() : dir;
+    try {
+      process.chdir(dir);
+      if (vpl) {
+        delimiter.refresh(vpl);
+      }
+      return 0;
+    } catch (e) {
+      return cd.error.call(self, e, dir);
+    }
+  },
+  error: function error(e, dir) {
+    var status = undefined;
+    var stdout = undefined;
+    if (e.code === 'ENOENT' && e.syscall === 'uv_chdir') {
+      status = 1;
+      stdout = '-bash: cd: ' + dir + ': No such file or directory';
+    } else {
+      status = 2;
+      stdout = e.stack;
+    }
+    this.log(stdout);
+    return status;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cd;
+  }
+  vorpal.api.cd = cd;
+  vorpal.command('cd [dir]').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: cd,
+      args: args.dir,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/cp.js b/dist/commands/cp.js
new file mode 100755
index 0000000..cce41f0
--- /dev/null
+++ b/dist/commands/cp.js
@@ -0,0 +1,207 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+var os = require('os');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var cp = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+
+    args = args === undefined ? [] : args;
+    args = _.isArray(args) ? args : args.split(' ');
+    args = _.filter(args, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    options.noclobber = options.force === true ? false : options.noclobber;
+    options.recursive = options.R === true ? true : options.recursive;
+
+    if (args.length < 1) {
+      this.log('cp: missing file operand\nTry \'cp --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log('cp: missing destination file operand after ' + args[0] + '\nTry \'cp --help\' for more information.');
+      return 1;
+    }
+
+    args = expand(args);
+
+    var dest = args.pop();
+    var sources = args;
+
+    var exists = fs.existsSync(dest);
+    var stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log('cp: target ' + dest + ' is not a directory');
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.recursive) {
+      sources.forEach(function (src, i) {
+        if (src[src.length - 1] === '/') {
+          sources[i] += '*';
+        } else if (fs.statSync(src).isDirectory() && !exists) {
+          sources[i] += '/*';
+        }
+      });
+      try {
+        fs.mkdirSync(dest, parseInt('0777', 8));
+      } catch (e) {
+        // like Unix's cp, keep going even if we can't create dest dir
+      }
+    }
+
+    sources = expand(sources);
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log('cp: cannot stat ' + src + ': No such file or directory');
+        return;
+      }
+
+      if (fs.statSync(src).isDirectory()) {
+        if (!options.recursive) {
+          self.log('cp: omitting directory ' + src);
+        } else {
+          // 'cp /a/source dest' should create 'source' in 'dest'
+          var newDest = path.join(dest, path.basename(src));
+          var checkDir = fs.statSync(src);
+          try {
+            fs.mkdirSync(newDest, checkDir.mode);
+          } catch (e) {
+            /* istanbul ignore if */
+            if (e.code !== 'EEXIST') {
+              throw new Error();
+            }
+          }
+          cpdirSyncRecursive.call(self, src, newDest, options);
+        }
+        return;
+      }
+
+      // If here, src is a file
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      var iDest = dest;
+      if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
+        iDest = path.normalize(dest + '/' + path.basename(src));
+      }
+
+      if (fs.existsSync(iDest) && options.no_force) {
+        return;
+      }
+
+      copyFileSync.call(self, src, iDest);
+    });
+  }
+};
+
+function cpdirSyncRecursive(sourceDir, destDir, options) {
+  var self = this;
+  /* istanbul ignore if */
+  if (!options) {
+    options = {};
+  }
+  var checkDir = fs.statSync(sourceDir);
+  try {
+    fs.mkdirSync(destDir, checkDir.mode);
+  } catch (e) {
+    /* istanbul ignore if */
+    if (e.code !== 'EEXIST') {
+      throw e;
+    }
+  }
+  var files = fs.readdirSync(sourceDir);
+  for (var i = 0; i < files.length; i++) {
+    var srcFile = sourceDir + '/' + files[i];
+    var destFile = destDir + '/' + files[i];
+    var srcFileStat = fs.lstatSync(srcFile);
+    if (srcFileStat.isDirectory()) {
+      // recursion this thing right on back.
+      cpdirSyncRecursive.call(self, srcFile, destFile, options);
+    } else if (srcFileStat.isSymbolicLink()) {
+      var symlinkFull = fs.readlinkSync(srcFile);
+      fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null);
+      // At this point, we've hit a file actually worth copying... so copy it on over.
+    } else if (fs.existsSync(destFile) && options.noclobber) {
+        // be silent
+      } else {
+          copyFileSync.call(self, srcFile, destFile);
+        }
+  }
+}
+
+function copyFileSync(src, dest) {
+  /* istanbul ignore if */
+  if (!fs.existsSync(src)) {
+    this.log('cp: cannot stat ' + src + ': No such file or directory');
+    return;
+  }
+
+  var BUF_LENGTH = 64 * 1024;
+  var buf = new Buffer(BUF_LENGTH);
+  var bytesRead = BUF_LENGTH;
+  var pos = 0;
+  var fdr = null;
+  var fdw = null;
+
+  try {
+    fdr = fs.openSync(src, 'r');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log('cp: cannot open ' + src + ': ' + e.code);
+    /* istanbul ignore next */
+    return;
+  }
+
+  try {
+    fdw = fs.openSync(dest, 'w');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log('cp: cannot write to destination file ' + dest + ': ' + e.code);
+    /* istanbul ignore next */
+    return;
+  }
+
+  while (bytesRead === BUF_LENGTH) {
+    bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+    fs.writeSync(fdw, buf, 0, bytesRead);
+    pos += bytesRead;
+  }
+
+  fs.closeSync(fdr);
+  fs.closeSync(fdw);
+  fs.chmodSync(dest, fs.statSync(src).mode);
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cp;
+  }
+  vorpal.api.cp = cp;
+  vorpal.command('cp [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('-r, --recursive', 'copy directories recursively').option('-R', 'copy directories recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: cp,
+      args: args.args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/echo.js b/dist/commands/echo.js
new file mode 100755
index 0000000..1bde3c3
--- /dev/null
+++ b/dist/commands/echo.js
@@ -0,0 +1,78 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var echo = {
+  exec: function exec(arg, options) {
+    var self = this;
+    options = options || {};
+
+    try {
+      var text = arg || '';
+      text = !_.isArray(text) ? [text] : text;
+      var result = text.join(' ');
+      var out = '';
+      if (options.e && !options.E) {
+        for (var i = 0; i < result.length; ++i) {
+          var nxt = result[i] + (result[i + 1] || '');
+          if (nxt === '\\b') {
+            out = out.slice(0, out.length - 1);
+            i++;
+          } else if (nxt === '\\c') {
+            break;
+          } else if (nxt === '\\n') {
+            out += '\n';
+            i++;
+          } else if (nxt === '\\r') {
+            out += '\r';
+            i++;
+          } else if (nxt === '\\t') {
+            out += '     ';
+            i++;
+          } else if (nxt === '\\\\') {
+            out += '\\';
+            i += 2;
+          } else {
+            out += result[i];
+          }
+        }
+        result = out;
+      }
+
+      // Bug: If nothing is passed, ensure we keep
+      // a blank line. Vorpal is designed to just
+      // eat blank lines, so we have a problem.
+      result = result === '' ? '' : result;
+
+      this.log(result);
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      return echo.error.call(self, e);
+    }
+  },
+  error: function error(e) {
+    /* istanbul ignore next */
+    this.log(e.stack);
+    /* istanbul ignore next */
+    return 2;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return echo;
+  }
+  vorpal.api.echo = echo;
+  vorpal.command('echo [arg...]').option('-e', 'enable interpretation of the following backslash escapes').option('-E', 'explicitly suppress interpretation of backslash escapes').action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: echo,
+      args: args.arg,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/grep.js b/dist/commands/grep.js
new file mode 100755
index 0000000..df4bc02
--- /dev/null
+++ b/dist/commands/grep.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-grep');
\ No newline at end of file
diff --git a/dist/commands/kill.js b/dist/commands/kill.js
new file mode 100755
index 0000000..226ded1
--- /dev/null
+++ b/dist/commands/kill.js
@@ -0,0 +1,97 @@
+'use strict';
+
+var _ = require('lodash');
+var fkill = require('fkill');
+var os = require('os');
+
+var interfacer = require('./../util/interfacer');
+
+var usage = 'kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]';
+var windows = os.platform().indexOf('win') > -1;
+var signals = {
+  SIGKILL: 9,
+  SIGTERM: 15,
+  KILL: 9,
+  TERM: 15,
+  9: 'KILL',
+  15: 'TERM'
+};
+
+var kill = {
+  exec: function exec(args, options) {
+    options = options || {};
+
+    var procs = args;
+    procs = procs === undefined ? [] : procs;
+    procs = typeof procs === 'string' ? String(procs).split(' ') : procs;
+    procs = _.filter(procs, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    function log(str) {
+      if (options.vorpal) {
+        options.vorpal.log(str);
+      } else {
+        /* istanbul ignore next */
+        console.log(str);
+      }
+    }
+
+    if (options.l !== undefined) {
+      if (options.l === true) {
+        this.log(' 9) SIGKILL   15) SIGTERM');
+        return 0;
+      }
+      if (signals[options.l]) {
+        this.log(signals[options.l]);
+        return 0;
+      }
+      this.log('-cash: kill: ' + options.l + ': invalid signal specification');
+      return 0;
+    }
+
+    if (procs.length < 1) {
+      this.log(usage);
+      return 0;
+    }
+
+    var forced = options['9'] === true || options.n === 9 || String(options.s).toLowerCase() === 'sigkill' || String(options.s).toLowerCase() === 'kill';
+    var opts = { force: forced };
+
+    var _loop = function _loop(i) {
+      var proc = procs[i];
+      proc = !isNaN(proc) ? parseFloat(proc) : proc;
+      proc = windows && isNaN(proc) && proc.indexOf('.') === -1 ? proc + '.exe' : proc;
+      fkill(proc, opts).then(function () {
+        // .. chill
+      }).catch(function (err) {
+        if (String(err.message).indexOf('failed') > -1) {
+          log('-cash: kill: (' + proc + ') - No such process');
+        }
+      });
+    };
+
+    for (var i = 0; i < procs.length; ++i) {
+      _loop(i);
+    }
+
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return kill;
+  }
+  vorpal.api.kill = kill;
+  vorpal.command('kill [process...]').option('-9', 'sigkill').option('-s [sig]', 'sig is a signal name').option('-n [sig]', 'sig is a signal number').option('-l [sigspec]', 'list the signal names').action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: kill,
+      args: args.process,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/less.js b/dist/commands/less.js
new file mode 100755
index 0000000..85673c1
--- /dev/null
+++ b/dist/commands/less.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-less');
\ No newline at end of file
diff --git a/dist/commands/ls.js b/dist/commands/ls.js
new file mode 100755
index 0000000..0055439
--- /dev/null
+++ b/dist/commands/ls.js
@@ -0,0 +1,353 @@
+'use strict';
+
+var _ = require('lodash');
+var chalk = require('chalk');
+var filesize = require('filesize');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var os = require('os');
+
+var colorFile = require('./../util/colorFile');
+var columnify = require('./../util/columnify');
+var dateConverter = require('./../util/converter.date');
+var fileFromPath = require('./../util/fileFromPath');
+var interfacer = require('./../util/interfacer');
+var pad = require('./../util/pad');
+var lpad = require('./../util/lpad');
+var permissionsConverter = require('./../util/converter.permissions');
+var strip = require('./../util/stripAnsi');
+var walkDir = require('./../util/walkDir');
+var walkDirRecursive = require('./../util/walkDirRecursive');
+
+var pads = { pad: pad, lpad: lpad };
+
+var ls = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec: function exec(paths, options) {
+    var self = this;
+    paths = !_.isArray(paths) && _.isObject(paths) ? paths.paths : paths;
+    paths = paths || ['.'];
+    paths = _.isArray(paths) ? paths : [paths];
+    options = options || {};
+    try {
+      var results = [];
+      for (var i = 0; i < paths.length; ++i) {
+        if (options.recursive) {
+          var result = ls.execDirRecursive(paths[i], options);
+          results = results.concat(result);
+        } else {
+          var result = ls.execDir(paths[i], options);
+          results.push(result);
+        }
+      }
+      var stdout = ls.formatAll(results, options);
+      if (strip(stdout).trim() !== '') {
+        self.log(String(stdout).replace(/\\/g, '/'));
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      return ls.error.call(self, e);
+    }
+  },
+
+
+  /**
+   * Returns ls stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error: function error(e) {
+    /* istanbul ignore next */
+    var status = undefined;
+    /* istanbul ignore next */
+    var stdout = undefined;
+    /* istanbul ignore next */
+    if (e.code === 'ENOENT' && e.syscall === 'scandir') {
+      status = 1;
+      stdout = 'ls: cannot access: No such file or directory';
+    } else {
+      /* istanbul ignore next */
+      status = 2;
+      /* istanbul ignore next */
+      stdout = e.stack;
+    }
+    /* istanbul ignore next */
+    this.log(stdout);
+    /* istanbul ignore next */
+    return status;
+  },
+
+
+  /**
+   * Recursively executes `execDir`.
+   * For use with `ls -R`.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDirRecursive: function execDirRecursive(path, options) {
+    var self = this;
+    var results = [];
+    walkDirRecursive(path, function (pth) {
+      var result = self.execDir(pth, options);
+      results.push(result);
+    });
+    return results;
+  },
+
+
+  /**
+   * Executes `ls` functionality
+   * for a given directory.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDir: function execDir(path, options) {
+    var files = [];
+    var rawFiles = [];
+    var totalSize = 0;
+
+    function pushFile(file, data) {
+      rawFiles.push({
+        file: file,
+        data: data
+      });
+    }
+
+    // Add in implied current and parent dirs.
+    pushFile('.', fs.statSync('.'));
+    pushFile('..', fs.statSync('..'));
+
+    // Walk the passed in directory,
+    // pushing the results into `rawFiles`.
+    walkDir(path, pushFile);
+
+    // Sort alphabetically be default,
+    // unless -U is specified, in which case
+    // we don't sort.
+    if (!options.U) {
+      rawFiles = rawFiles.sort(function (a, b) {
+        // Sort by size.
+        if (options.S) {
+          // Hack for windows - a directory lising
+          // in linux says the size is 4096, and Windows
+          // it's 0, leading to inconsistent sorts based
+          // on size, and failing tests.
+          var win = os.platform() === 'win32';
+          a.data.size = win && a.data.isDirectory() && a.data.size === 0 ? 4096 : a.data.size;
+          b.data.size = win && b.data.isDirectory() && b.data.size === 0 ? 4096 : b.data.size;
+          return a.data.size > b.data.size ? -1 : a.data.size < b.data.size ? 1 : 0;
+        }
+        if (options.t) {
+          // Sort by date modified.
+          return a.data.mtime < b.data.mtime ? 1 : b.data.mtime < a.data.mtime ? -1 : 0;
+        }
+        // Sort alphabetically - default.
+        var aFileName = fileFromPath(a.file).trim().toLowerCase().replace(/\W/g, '');
+        var bFileName = fileFromPath(b.file).trim().toLowerCase().replace(/\W/g, '');
+        return aFileName > bFileName ? 1 : aFileName < bFileName ? -1 : 0;
+      });
+    }
+
+    // Reverse whatever sort the user specified.
+    if (options.reverse) {
+      rawFiles.reverse();
+    }
+
+    var _loop = function _loop(i) {
+      var file = rawFiles[i].file;
+      var data = rawFiles[i].data;
+      var fileShort = fileFromPath(file);
+      var dotted = fileShort && fileShort.charAt(0) === '.';
+      var implied = fileShort === '..' || fileShort === '.';
+      var type = data.isDirectory() ? 'd' : '-';
+      var permissions = permissionsConverter.modeToRWX(data.mode);
+      var hardLinks = data.nlink;
+      var size = options.humanreadable ? filesize(data.size, { unix: true }) : data.size;
+      var modified = dateConverter.unix(data.mtime);
+      var owner = data.uid;
+      var group = data.gid;
+      var inode = data.ino;
+
+      totalSize += data.size;
+
+      var fileName = fileShort;
+
+      // If --classify, add '/' to end of folders.
+      fileName = options.classify && data.isDirectory() ? fileName + '/' : fileName;
+
+      // If getting --directory, give full path.
+      fileName = options.directory && file === '.' ? path : fileName;
+
+      // Color the files based on $LS_COLORS
+      fileName = data.isFile() ? colorFile(fileName) : fileName;
+
+      // If not already colored and is executable,
+      // make it green
+      var colored = strip(fileName) !== fileName;
+      if (String(permissions).indexOf('x') > -1 && !colored && data.isFile()) {
+        fileName = chalk.green(fileName);
+      }
+
+      // If --quote-name, wrap in double quotes;
+      fileName = options.quotename ? '"' + fileName + '"' : fileName;
+
+      // Make directories cyan.
+      fileName = data.isDirectory() ? chalk.cyan(fileName) : fileName;
+
+      var include = function () {
+        var directory = options.directory;
+        var all = options.all;
+        var almostAll = options.almostall;
+        var result = false;
+        if (directory && file !== '.') {
+          result = false;
+        } else if (!dotted) {
+          result = true;
+        } else if (all) {
+          result = true;
+        } else if (!implied && almostAll) {
+          result = true;
+        } else if (directory && file === '.') {
+          result = true;
+        }
+        return result;
+      }();
+
+      var details = [type + permissions, hardLinks, owner, group, size, modified, fileName];
+
+      if (options.inode) {
+        details.unshift(inode);
+      }
+
+      var result = options.l && !options.x ? details : fileName;
+
+      if (include) {
+        files.push(result);
+      }
+    };
+
+    for (var i = 0; i < rawFiles.length; ++i) {
+      _loop(i);
+    }
+
+    var result = undefined;
+
+    // If we have the detail view, draw out
+    // all of the details of each file.
+    // Otherwise, just throw the file names
+    // into columns.
+    if (_.isArray(files[0])) {
+      var longest = {};
+      for (var i = 0; i < files.length; ++i) {
+        for (var j = 0; j < files[i].length; ++j) {
+          var len = String(files[i][j]).length;
+          longest[j] = longest[j] || 0;
+          longest[j] = len > longest[j] ? len : longest[j];
+        }
+      }
+
+      var newFiles = [];
+      for (var i = 0; i < files.length; ++i) {
+        var glob = '';
+        for (var j = 0; j < files[i].length; ++j) {
+          var padFn = j === files[i].length - 1 ? 'pad' : 'lpad';
+          if (j === files[i].length - 1) {
+            glob += String(files[i][j]);
+          } else {
+            glob += pads[padFn](String(files[i][j]), longest[j], ' ') + ' ';
+          }
+        }
+        newFiles.push(String(glob));
+      }
+      result = newFiles.join('\n');
+    } else if (options['1']) {
+      result = files.join('\n');
+    } else {
+      var opt = {};
+      if (options.width) {
+        opt.width = options.width;
+      }
+      result = columnify(files, opt);
+    }
+
+    return {
+      path: path,
+      size: options.humanreadable ? filesize(totalSize, { unix: true }) : totalSize,
+      results: result
+    };
+  },
+
+
+  /**
+   * Concatenates the results of multiple
+   * `execDir` functions into their proper
+   * form based on options provided.
+   *
+   * @param {String} results
+   * @param {Object} options
+   * @return {String} stdout
+   * @api private
+   */
+
+  formatAll: function formatAll(results, options) {
+    var stdout = '';
+    if (results.length > 1) {
+      for (var i = 0; i < results.length; ++i) {
+        stdout += results[i].path + ':\n';
+        if (options.l) {
+          stdout += 'total ' + results[i].size + '\n';
+        }
+        stdout += results[i].results;
+        if (i !== results.length - 1) {
+          stdout += '\n\n';
+        }
+      }
+    } else if (results.length === 1) {
+      if (options.l && !options.x) {
+        stdout += 'total ' + results[0].size + '\n';
+      }
+      stdout += results[0].results;
+    }
+    return stdout;
+  }
+};
+
+/**
+ * Expose as a Vorpal extension.
+ */
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return ls;
+  }
+  vorpal.api.ls = ls;
+  vorpal.command('ls [paths...]').option('-a, --all', 'do not ignore entries starting with .').option('-A, --almost-all', 'do not list implied . and ..').option('-d, --directory', 'list directory entries instead of contents, and do not dereference symbolic links').option('-F, --classify', 'append indicator (one of */=>@|) to entries').option('-h, --human-readable', 'with -l, print sizes in human readable format (e.g., 1K 234M 2G)').option('-i, --inode', 'print the index number of each file').option('-l', 'use a long listing format').option('-Q, --quote-name', 'enclose entry names in double quotes').option('-r, --reverse', 'reverse order while sorting').option('-R, --recursive', 'list subdirectories recursively').option('-S', 'sort by file size').option('-t', 'sort by modification time, newest first').option('-U', 'do not sort; list entries in directory order').option('-w, --width [COLS]', 'assume screen width instead of current value').option('-x', 'list entries by lines instead of columns').option('-1', 'list one file per line').autocomplete(fsAutocomplete()).action(function (args, cb) {
+    return interfacer.call(this, {
+      command: ls,
+      args: args.paths,
+      options: args.options,
+      callback: cb
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/mkdir.js b/dist/commands/mkdir.js
new file mode 100755
index 0000000..8f92c96
--- /dev/null
+++ b/dist/commands/mkdir.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+
+var mkdir = {
+  exec: function exec(args, options) {
+    var self = this;
+    var dirs = args || [];
+    options = options || {};
+
+    if (typeof dirs === 'string') {
+      dirs = dirs.split(' ');
+    }
+
+    dirs = dirs.filter(function (str) {
+      return String(str).trim() !== '';
+    });
+
+    if (dirs.length < 1) {
+      this.log('mkdir: missing operand\nTry \'mkdir --help\' for more information.');
+    }
+
+    dirs.forEach(function (dir) {
+      if (fs.existsSync(dir)) {
+        if (!options.parents) {
+          self.log('mkdir: cannot create directory ' + dir + ': File exists');
+        }
+        return;
+      }
+
+      // Base dir does not exist, and no -p option given
+      var baseDir = path.dirname(dir);
+      if (!fs.existsSync(baseDir) && !options.parents) {
+        self.log('mkdir: cannot create directory ' + dir + ': No such file or directory');
+        return;
+      }
+
+      if (options.parents) {
+        mkdirSyncRecursive.call(self, dir, options);
+      } else {
+        fs.mkdirSync(dir, parseInt('0777', 8));
+        if (options.verbose) {
+          self.log('mkdir: created directory ' + dir);
+        }
+      }
+    });
+    return 0;
+  }
+};
+
+function mkdirSyncRecursive(dir, options) {
+  var baseDir = path.dirname(dir);
+  if (fs.existsSync(baseDir)) {
+    fs.mkdirSync(dir, parseInt('0777', 8));
+    if (options.verbose) {
+      this.log('mkdir: created directory ' + dir);
+    }
+    return;
+  }
+  mkdirSyncRecursive.call(this, baseDir, options);
+  fs.mkdirSync(dir, parseInt('0777', 8));
+  if (options.verbose) {
+    this.log('mkdir: created directory ' + dir);
+  }
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mkdir;
+  }
+  vorpal.api.mkdir = mkdir;
+  vorpal.command('mkdir [directory...]').option('-p, --parents', 'no error if existing, make parent directories as needed').option('-v, --verbose', 'print a message for each created directory').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: mkdir,
+      args: args.directory,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/mv.js b/dist/commands/mv.js
new file mode 100755
index 0000000..9a79232
--- /dev/null
+++ b/dist/commands/mv.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var mv = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+
+    args = args === undefined ? [] : args;
+    args = _.isArray(args) ? args : args.split(' ');
+    args = _.filter(args, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    options.noclobber = options.force === true ? false : options.noclobber;
+
+    if (args.length < 1) {
+      this.log('mv: missing file operand\nTry \'mv --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log('mv: missing destination file operand after ' + args[0] + '\nTry \'mv --help\' for more information.');
+      return 1;
+    }
+
+    args = expand(args);
+
+    var dest = args.pop();
+    var sources = args;
+
+    var exists = fs.existsSync(dest);
+    var stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log('mv: target ' + dest + ' is not a directory');
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.striptrailingslashes) {
+      sources = sources.map(function (src) {
+        return String(src).replace(/\/$/g, '');
+      });
+    }
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log('mv: cannot stat ' + src + ': No such file or directory');
+        return;
+      }
+
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      var iDest = dest;
+      if (exists && stats.isDirectory()) {
+        iDest = path.normalize(dest + '/' + path.basename(src));
+      }
+
+      // If the file exists and we're not clobbering, skip.
+      if (fs.existsSync(iDest) && options.noclobber) {
+        return;
+      }
+
+      if (path.resolve(src) === path.dirname(path.resolve(iDest))) {
+        self.log('mv: ' + src + ' and ' + iDest + ' are the same file');
+        return;
+      }
+
+      fs.renameSync(src, iDest);
+      if (options.verbose === true) {
+        self.log(String(src + ' -> ' + iDest).replace(/\\/g, '/'));
+      }
+    });
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mv;
+  }
+  vorpal.api.mv = mv;
+  vorpal.command('mv [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('--striptrailingslashes', 'remove any trailing slashes from each source') // vorpal bug, need to add dashes between words
+  .option('-v, --verbose', 'explain what is being done').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: mv,
+      args: args.args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/pwd.js b/dist/commands/pwd.js
new file mode 100755
index 0000000..b46eca7
--- /dev/null
+++ b/dist/commands/pwd.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var path = require('path');
+
+var interfacer = require('./../util/interfacer');
+
+var pwd = {
+  exec: function exec() {
+    this.log(path.resolve(process.cwd()).replace(/\\/g, '/'));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return pwd;
+  }
+  vorpal.api.pwd = pwd;
+  vorpal.command('pwd [files...]').action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: pwd,
+      args: args.files,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/rm.js b/dist/commands/rm.js
new file mode 100755
index 0000000..502f359
--- /dev/null
+++ b/dist/commands/rm.js
@@ -0,0 +1,171 @@
+'use strict';
+
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+var unlinkSync = require('./../util/unlinkSync');
+
+var rm = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+    options.recursive = options.R ? options.R : options.recursive;
+
+    var files = args;
+    files = files === undefined ? [] : files;
+    files = typeof files === 'string' ? [files] : files;
+
+    files = expand(files);
+
+    files.forEach(function (file) {
+      if (!fs.existsSync(file)) {
+        // Path does not exist, no force flag given
+        if (!options.force) {
+          self.log('rm: cannot remove ' + file + ': No such file or directory');
+          return 2;
+        }
+        /* istanbul ignore next */
+        return 0;
+      }
+
+      var stats = fs.lstatSync(file);
+      if (stats.isFile() || stats.isSymbolicLink()) {
+        if (options.force) {
+          unlinkSync(file);
+          return 0;
+        }
+
+        if (isWriteable(file)) {
+          unlinkSync(file);
+        } else {
+          /* istanbul ignore next */
+          self.log('rm: cannot remove ' + file + ': permission denied');
+          /* istanbul ignore next */
+          return 2;
+        }
+        return 0;
+      }
+
+      // Path is an existing directory, but no -r flag given
+      if (stats.isDirectory() && !options.recursive) {
+        self.log('rm: cannot remove: path is a directory');
+        return 2;
+      }
+
+      // Recursively remove existing directory
+      if (stats.isDirectory() && options.recursive) {
+        rmdirSyncRecursive.call(self, file, options.force, options.dir);
+      }
+    });
+  }
+};
+
+function rmdirSyncRecursive(dir, force, removeEmptyDir) {
+  var self = this;
+  var files = undefined;
+  files = fs.readdirSync(dir);
+
+  // Loop through and delete everything in the sub-tree after checking it
+  for (var i = 0; i < files.length; i++) {
+    var file = dir + '/' + files[i];
+    var currFile = fs.lstatSync(file);
+
+    if (currFile.isDirectory()) {
+      // Recursive function back to the beginning
+      rmdirSyncRecursive(file, force, removeEmptyDir);
+    } else if (currFile.isSymbolicLink()) {
+      // Unlink symlinks
+      /* istanbul ignore next */
+      if (force || isWriteable(file)) {
+        try {
+          unlinkSync(file);
+        } catch (e) {
+          self.log('rm: cannot remove ' + file + ': code ' + e.code);
+          return 2;
+        }
+      }
+    } else if (force || isWriteable(file)) {
+      // Assume it's a file.
+      try {
+        unlinkSync(file);
+      } catch (e) {
+        /* istanbul ignore next */
+        self.log('rm: cannot remove ' + file + ': code ' + e.code);
+        /* istanbul ignore next */
+        return 2;
+      }
+    }
+  }
+
+  // Now that we know everything in the sub-tree has been deleted,
+  // we can delete the main directory.
+  var result = undefined;
+  try {
+    // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+    var start = Date.now();
+    while (true) {
+      try {
+        result = fs.rmdirSync(dir);
+        /* istanbul ignore next */
+        if (fs.existsSync(dir)) {
+          throw new Error('EAGAIN');
+        }
+        break;
+      } catch (er) {
+        // In addition to error codes, also check if the directory still exists and loop again if true
+        /* istanbul ignore next */
+        if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+          if (Date.now() - start > 1000) {
+            throw er;
+          }
+          /* istanbul ignore next */
+        } else if (er.code === 'ENOENT') {
+            // Directory did not exist, deletion was successful
+            break;
+            /* istanbul ignore next */
+          } else {
+              throw er;
+            }
+      }
+    }
+  } catch (e) {
+    /* istanbul ignore next */
+    self.log('rm: cannot remove directory ' + dir + ': code ' + e.code);
+    /* istanbul ignore next */
+    return 2;
+  }
+  return result;
+}
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow.
+function isWriteable(file) {
+  var writePermission = true;
+  try {
+    var __fd = fs.openSync(file, 'a');
+    fs.closeSync(__fd);
+  } catch (e) {
+    /* istanbul ignore next */
+    writePermission = false;
+  }
+
+  return writePermission;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return rm;
+  }
+  vorpal.api.rm = rm;
+  vorpal.command('rm [files...]').option('-f, --force', 'ignore nonexistent files and arguments, never prompt').option('-r, --recursive', 'remove directories and their contents recursively').option('-R', 'remove directories and their contents recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: rm,
+      args: args.files,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/sort.js b/dist/commands/sort.js
new file mode 100755
index 0000000..0212ca0
--- /dev/null
+++ b/dist/commands/sort.js
@@ -0,0 +1,269 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var strip = require('./../util/stripAnsi');
+
+var sort = {
+
+  counter: 0,
+
+  stdin: '',
+
+  exec: function exec(args, options) {
+    var self = this;
+
+    // Hack to handle multiple calls
+    // due to fragmented stdin, such as
+    // by piping. In essence, we're waiting
+    // 100 milliseconds for all of the
+    // requests to come in, and then running
+    // sort. Only applies when sort is called
+    // through a piped command.
+    /* istanbul ignore next */
+    if (args && args.stdin && options.bypass !== true) {
+      sort.counter++;
+      sort.stdin += args.stdin + '\n';
+      if (sort.counter === 1) {
+        setTimeout(function () {
+          sort.counter = 0;
+          args.stdin = sort.stdin;
+          sort.stdin = '';
+          options.bypass = true;
+          sort.exec.call(self, args, options);
+        }, 100);
+      }
+      return;
+    }
+    sort.counter = 0;
+    sort.stdin = '';
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    function log(stdout) {
+      if (options.output) {
+        if (options.output === true) {
+          self.log('sort: option \'--output\' requires an argument\nTry \'sort --help\' for more information.');
+          return 0;
+        }
+        try {
+          fs.writeFileSync(options.output, stdout);
+          return 0;
+        } catch (e) {
+          if (e.code === 'ENOENT') {
+            self.log('sort: open failed: ' + options.output + ': No such file or directory');
+          } else {
+            /* istanbul ignore next */
+            self.log('sort: open failed: ' + options.output + ': ' + e.code);
+          }
+          return 2;
+        }
+      } else {
+        self.log(stdout);
+      }
+    }
+
+    try {
+      var stdin = fetch(args.files, args.stdin, {
+        onDirectory: function onDirectory(name) {
+          /* istanbul ignore next */
+          return 'sort: read failed: ' + name + ': Is a directory';
+        },
+        onInvalidFile: function onInvalidFile(name) {
+          /* istanbul ignore next */
+          return 'sort: cannot read: ' + name + ': No such file or directory';
+        }
+      });
+
+      var combined = '';
+      for (var i = 0; i < stdin.length; ++i) {
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        combined += stdin[i];
+      }
+
+      combined = combined.replace(/\s$/, '');
+      var parts = String(combined).split('\n');
+
+      if (options.check) {
+        // Check if the thing was already sorted.
+        var original = String(combined).split('\n');
+        var disorder = undefined;
+        for (var i = 0; i < original.length; ++i) {
+          var a = original[i];
+          var b = original[i + 1];
+          if (a && b) {
+            if (!isNaN(a) && !isNaN(b) && parseFloat(a) > parseFloat(b)) {
+              /* istanbul ignore next */
+              disorder = true;
+            } else if (a > b) {
+              disorder = true;
+            }
+            if (disorder) {
+              // To do: right now, I don't say the file
+              // name of the bad sorted item - I have to
+              // figure this out as I join all the files
+              // together beforehand and lose track.
+              disorder = 'sort: -:' + (i + 2) + ': disorder: ' + b;
+              break;
+            }
+          }
+        }
+        if (disorder) {
+          log(disorder);
+          return;
+        }
+      }
+
+      parts = parts.sort(function (a, b) {
+        var aAlpha = strip(a).replace(/\W+/g, '');
+        var bAlpha = strip(b).replace(/\W+/g, '');
+        var aNumeric = strip(a).replace(/\D/g, '');
+        var bNumeric = strip(b).replace(/\D/g, '');
+        if (options.humannumericsort) {
+          var aHuman = parseHumanReadableNumbers(strip(a));
+          var bHuman = parseHumanReadableNumbers(strip(b));
+          if (aHuman.group < bHuman.group) {
+            return -1;
+          } else if (aHuman.group > bHuman.group) {
+            return 1;
+          } else if (aHuman.num < bHuman.num) {
+            return -1;
+          } else if (aHuman.num > bHuman.num) {
+            return 1;
+          }
+          return aAlpha.localeCompare(bAlpha);
+        } else if (options.monthsort) {
+          var aMonth = parseMonths(strip(a));
+          var bMonth = parseMonths(strip(b));
+          var result = aMonth - bMonth;
+          if (aMonth === bMonth) {
+            result = aAlpha.localeCompare(bAlpha);
+          }
+          return result;
+        } else if (options.numericsort) {
+          var result = aNumeric - bNumeric;
+          result = result === 0 ? aAlpha.localeCompare(bAlpha) : result;
+          return result;
+        }
+        return aAlpha.localeCompare(bAlpha);
+      });
+
+      if (options.randomsort) {
+        fisherYatesShuffle(parts);
+      }
+
+      if (options.reverse) {
+        parts.reverse();
+      }
+
+      var out = parts.join('\n');
+      if (String(out).trim() !== '') {
+        log(out);
+      }
+
+      return;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return;
+    }
+  }
+};
+
+// This shit is gnarly.
+// Per the coreutils sort.c:
+// <none/unknown> < K/k < M < G < T < P < E < Z < Y
+var humanOrdering = { '': 0, 'K': 1, 'k': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7 };
+var humanReadableSort = new RegExp(/^([0-9]+)?[\.]?[0-9]+[K|k|M|G|T|P|E|Z|Y]/g);
+function parseHumanReadableNumbers(nbr) {
+  nbr = String(nbr).replace(/(\r\n|\n|\r)/gm, '');
+  if (String(nbr).match(humanReadableSort)) {
+    var num = parseFloat(String(nbr).replace(/[a-zA-Z]/g, '').trim());
+    var group = humanOrdering[String(nbr).replace(/[^a-zA-Z]/g, '').trim()] || 0;
+    return {
+      num: num,
+      group: group
+    };
+  }
+  var isNumber = String(nbr).match(/^[0-9]/);
+  var stripped = isNumber ? parseFloat(String(nbr).replace(/[^0-9.]/g, '')) : 'NaN';
+  var result = !isNaN(stripped) ? stripped : -99999999999;
+  return {
+    num: result,
+    group: 0
+  };
+}
+
+var monthOrdering = {
+  jan: 1,
+  feb: 2,
+  mar: 3,
+  apr: 4,
+  may: 5,
+  jun: 6,
+  jul: 7,
+  aug: 8,
+  sep: 9,
+  oct: 10,
+  nov: 11,
+  dec: 12
+};
+
+var months = new RegExp(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i);
+function parseMonths(str) {
+  var match = String(str).match(months);
+  if (match) {
+    return monthOrdering[String(str.slice(0, 3).toLowerCase())];
+  }
+  return 0;
+}
+
+function fisherYatesShuffle(array) {
+  var m = array.length;
+  var t = undefined;
+  var i = undefined;
+  while (m) {
+    i = Math.floor(Math.random() * m--);
+    t = array[m];
+    array[m] = array[i];
+    array[i] = t;
+  }
+  return array;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return sort;
+  }
+  vorpal.api.sort = sort;
+  vorpal.command('sort [files...]').option('-M, --month-sort', 'compare (unknown) < \'JAN\' < ... < \'DEC\'').option('-h, --human-numeric-sort', 'compare human readable numbers (e.g., 2K 1G)').option('-n, --numeric-sort', 'compare according to string numerical value').option('-R, --random-sort', 'sort by random hash of keys').option('-r, --reverse', 'reverse the result of comparisons').option('-c, --check', 'check for sorted input; do not sort').option('-o, --output [file]', 'write result to file instead of standard output').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: sort,
+      args: args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/touch.js b/dist/commands/touch.js
new file mode 100755
index 0000000..d8b07cb
--- /dev/null
+++ b/dist/commands/touch.js
@@ -0,0 +1,151 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs-extra');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+require('./../lib/sugar');
+
+var touch = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec: function exec(files, options) {
+    var self = this;
+    files = files || ['.'];
+    files = !_.isArray(files) ? [files] : files;
+    options = options || {};
+
+    // If any version of --no-create is passed, change it to false.
+    options.create = options.create === true ? false : options.create;
+
+    // If --time is passed, ensure a valid param is called in
+    // and map it to -a or -m, as this is the equivalent of these.
+    // Throw an error if nothing valid passed.
+    if (options.time) {
+      var a = ['access', 'atime', 'use'];
+      var m = ['modify', 'mtime'];
+      var opt = a.indexOf(options.time) > -1 ? 'a' : m.indexOf(options.time) > -1 ? 'm' : undefined;
+      if (!opt) {
+        var error = 'touch: invalid argument "' + options.time + '" for "--time"\n' + 'Valid arguments are:\n' + '  - "atime", "access", "use"\n' + '  - "mtime", "modify"\n' + 'Try \'touch --help\' for more information.';
+        // I think this is the stupidest thing
+        // I've ever written.
+        try {
+          throw new Error(error);
+        } catch (e) {
+          return touch.error.call(self, e);
+        }
+      } else {
+        options[opt] = true;
+      }
+    }
+
+    try {
+      var err = false;
+      for (var i = 0; i < files.length; ++i) {
+        try {
+          touch.file(files[i], options);
+        } catch (e) {
+          err = e;
+          break;
+        }
+      }
+      if (err) {
+        return touch.error.call(self, err);
+      }
+      return 0;
+    } catch (e) {
+      return touch.error.call(self, e);
+    }
+  },
+
+  /**
+   * Returns touch stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error: function error(e) {
+    this.log(e.message);
+    return 2;
+  },
+
+  /**
+   * Handler for a single file using touch.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @api private
+   */
+
+  file: function file(path, options) {
+    try {
+      try {
+        fs.lstatSync(path);
+      } catch (e) {
+        // If the file doesn't exist and
+        // the user doesn't want to create it,
+        // we have no purpose in life. Goodbye.
+        if (options.create === false) {
+          throw new Error(e);
+        } else {
+          fs.closeSync(fs.openSync(path, 'wx'));
+        }
+      }
+
+      var stat = fs.statSync(path);
+      var dateToSet = options.date ? Date.create(options.date) : new Date();
+
+      if (String(dateToSet) === 'Invalid Date') {
+        throw new Error('touch: invalid date format ' + options.date);
+      }
+
+      // If -m, keep access time current.
+      var atime = options.m === true ? new Date(stat.atime) : dateToSet;
+
+      // If -a, keep mod time to current.
+      var mtime = options.a === true ? new Date(stat.mtime) : dateToSet;
+
+      if (options.reference !== undefined) {
+        var reference = undefined;
+        try {
+          reference = fs.statSync(options.reference);
+        } catch (e) {
+          throw new Error('touch: failed to get attributes of ' + options.reference + ': No such file or directory');
+        }
+        atime = options.m === true ? atime : reference.atime;
+        mtime = options.a === true ? mtime : reference.mtime;
+      }
+
+      fs.utimesSync(path, atime, mtime);
+      fs.utimesSync(path, atime, mtime);
+    } catch (e) {
+      throw new Error(e);
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return touch;
+  }
+  vorpal.api.touch = touch;
+  vorpal.command('touch <files...>').option('-a', 'change only the access time').option('-c, --no-create', 'do not create any files').option('-d, --date [STRING]', 'parse STRING and use it instead of current time').option('-m', 'change only the modification time').option('-r, --reference [FILE]', 'use this file\'s times instead of current time').option('--time [WORD]', 'change the specified time: WORD is access, atime, or use: equivalent to -a WORD is modify or mtime: equivalent to -m').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    return interfacer.call(this, {
+      command: touch,
+      args: args.files || [],
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/commands/unalias.js b/dist/commands/unalias.js
new file mode 100755
index 0000000..50a1708
--- /dev/null
+++ b/dist/commands/unalias.js
@@ -0,0 +1,100 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var unalias = {
+  exec: function exec(args, options) {
+    var _this = this;
+
+    args = args;
+    options = options || {};
+    var vorpal = options.vorpal;
+
+    if (!vorpal) {
+      /* istanbul ignore next */
+      throw new Error('Unalias is not programatically supported.');
+    }
+
+    vorpal._aliases = vorpal._aliases || [];
+
+    if (_.isString(args)) {
+      args = String(args).split(' ');
+      args = args.filter(function (str) {
+        return String(str).trim() !== '';
+      });
+    }
+
+    // Validate no input with help.
+    if ((args === undefined || args.length < 1 || args === '') && !options.a) {
+      this.log('unalias: usage: unalias [-a] name [name ...]');
+      return 1;
+    }
+
+    // Pull list of aliases
+    var all = undefined;
+    try {
+      all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      /* istanbul ignore next */
+      all = [];
+      /* istanbul ignore next */
+      vorpal.localStorage.removeItem('aliases');
+    }
+
+    if (options.a) {
+      args = all;
+    }
+
+    // Remove each alias in the list.
+
+    var _loop = function _loop(i) {
+      var key = args[i];
+      var item = vorpal.localStorage.getItem('alias|' + key);
+      if (item !== undefined && item !== null) {
+        vorpal.localStorage.removeItem('alias|' + key);
+      } else {
+        _this.log('-cash: unalias: ' + key + ': not found');
+      }
+      all = all.filter(function (str) {
+        return !(str === key);
+      });
+    };
+
+    for (var i = 0; i < args.length; ++i) {
+      _loop(i);
+    }
+
+    // Rebuild alias lists.
+    var aliases = {};
+    /* istanbul ignore next */
+    for (var i = 0; i < all.length; ++i) {
+      var item = vorpal.localStorage.getItem('alias|' + all[i]);
+      if (item !== undefined && item !== null) {
+        aliases[all[i]] = item;
+      }
+    }
+    vorpal._aliases = aliases;
+
+    vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return unalias;
+  }
+  vorpal.api.unalias = unalias;
+  vorpal.command('unalias [name...]').option('-a', 'remove all alias definitions').action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: unalias,
+      args: args.name,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/delimiter.js b/dist/delimiter.js
new file mode 100755
index 0000000..399022f
--- /dev/null
+++ b/dist/delimiter.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var os = require('os');
+var username = require('username');
+
+var pathConverter = require('./util/converter.path');
+
+module.exports = {
+  refresh: function refresh(vorpal, cb) {
+    cb = cb || function () {};
+    var self = this;
+    username(function (err, username) {
+      if (!err) {
+        var user = username;
+        var host = String(os.hostname()).split('.')[0];
+        var home = pathConverter.unix(self.getHomeDir());
+        var cwd = pathConverter.unix(process.cwd());
+        cwd = cwd.replace(home, '~');
+        var delimiter = user + '@' + host + ':' + cwd + '$';
+        // If we're on linux-based systems, color
+        // the prompt so we don't get confused.
+        if (os.platform().indexOf('win') === -1) {
+          delimiter = '\u001b[32m' + delimiter + '\u001b[39m';
+        }
+        vorpal.delimiter(delimiter);
+      }
+      cb(err);
+    });
+  },
+  getHomeDir: function getHomeDir() {
+    return process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'];
+  }
+};
\ No newline at end of file
diff --git a/dist/help.js b/dist/help.js
new file mode 100755
index 0000000..6b2162d
--- /dev/null
+++ b/dist/help.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var pad = require('./util/pad');
+
+var commands = ['alias [-p] [name=[value]]', 'cat [-AbeEnstTv] [files ...]', 'cd [dir]', 'cp [-fnr] source ... dest', 'echo [eE] [arg ...]', 'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]', 'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l', 'less [files ...]', 'ls [-aAdFhilQrRStUwx1] [paths ...]', 'mkdir [-pv] [directories ...]', 'mv [-fnv] source ... dest', 'pwd [files ...]', 'rm [-frR] [files ...]', 'sort [-chMnrR] [-o file] [files ...]', 'touch [-acm] [-d date] [-r ref] [--time word] file ...', 'unalias [-a] name [names ...]'];
+
+function chop(str, len) {
+  var res = String(str).slice(0, len - 2);
+  res = res.length === len - 2 ? res + '>' : res;
+  return res;
+}
+
+module.exports = function () {
+  var version = require('./../package.json').version;
+  var result = '';
+
+  result += 'Cash, version ' + version + '\n';
+  result += 'These shell commands are defined internally.  Type `help\' to see this list.\n';
+  result += 'Type `help name\' to find out more about the function `name\'.\n';
+  result += 'Use `info cash\' to find out more about the shell in general.\n';
+  result += '\n';
+
+  var half = Math.floor(commands.length / 2);
+  var width = Math.floor((process.stdout.columns - 3) / 2);
+  var lhalf = Math.ceil(commands.length / 2);
+  var padding = commands.length % 2 === 1 ? 1 : 0;
+  for (var i = 0; i < lhalf; ++i) {
+    var colA = pad(chop(commands[i], width), width);
+    var colB = pad(chop(commands[half + i + padding] || '', width), width);
+    var line = i === lhalf - 1 ? '' : '\n';
+    result += ' ' + colA + ' ' + colB + line;
+  }
+
+  return result;
+};
\ No newline at end of file
diff --git a/dist/help/alias.js b/dist/help/alias.js
new file mode 100755
index 0000000..7f8897a
--- /dev/null
+++ b/dist/help/alias.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: alias [OPTION] [name[=value] ...]\nDefine or display aliases.\n\nWithout arguments, `alias' prints the list of aliases in the reusable\nform `alias NAME=VALUE' on standard output.\n\nOtherwise, an alias is defined for each NAME whose VALUE is given.\nA trailing space in VALUE causes the next word to be checked for\nalias substitution when the alias is expanded.\n\n  -p           print all defined aliases in a reusable format\n      --help   display this help and exit\n\nReport alias bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/cat.js b/dist/help/cat.js
new file mode 100755
index 0000000..42872c7
--- /dev/null
+++ b/dist/help/cat.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cat [OPTION]... [FILE]...\nConcatenate FILE(s), or standard input, to standard output.\n\n  -A, --show-all           equivalent to -vET\n  -b, --number-nonblank    number nonempty output lines, overrides -n\n  -e                       equivalent to -vE\n  -E, --show-ends          display $ at end of each line\n  -n, --number             number all output lines\n  -s, --squeeze-blank      suppress repeated empty output lines\n  -t                       equivalent to -vT\n  -T, --show-tabs          display TAB characters as ^I\n  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB\n      --help               display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nExamples:\n  cat f - g  Output f's contents, then standard input, then g's contents.\n  cat        Copy standard input to standard output.\n\nReport cat bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/cd.js b/dist/help/cd.js
new file mode 100755
index 0000000..cdd6b29
--- /dev/null
+++ b/dist/help/cd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cd [DIR]...\nChange the cash working directory.\n\nChange the current directory to DIR.  The default DIR is the value of the\nHOME shell variable.\n\nReport cd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/cp.js b/dist/help/cp.js
new file mode 100755
index 0000000..52be2d7
--- /dev/null
+++ b/dist/help/cp.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cp [OPTION]... [-T] SOURCE DEST\n  or:  cp [OPTION]... SOURCE... DIRECTORY\nCopy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\n  -f, --force           if an existing destination file cannot be\n                          opened, remove it and try again (this option\n                          is ignored when the -n option is also used)\n  -n, --no-clobber      do not overwrite an existing file (overrides\n                          a previous -i option)\n  -R, -r, --recursive   copy directories recursively\n      --help            display this help and exit\n\nReport cp bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/echo.js b/dist/help/echo.js
new file mode 100755
index 0000000..692cbd6
--- /dev/null
+++ b/dist/help/echo.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: echo [OPTION]... [ARG ...]\nWrite arguments to the standard output.\n\nDisplay the ARGs, separated by a single space character and followed by a\nnewline, on the standard output.\n\n  -e           enable interpretation of the following backslash escapes\n  -e           explicitly suppress interpretation of backslash escapes\n      --help   display this help and exit\n\n  `echo' interprets the following backslash-escaped characters:\n    \b         backspace\n    c         suppress further output\n    \n         new line\n    \r         carriage return\n    \t         horizontal tab\n    \\         backslash\n\nReport echo bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/grep.js b/dist/help/grep.js
new file mode 100755
index 0000000..f10a4f7
--- /dev/null
+++ b/dist/help/grep.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: grep [OPTION]... PATTERN [FILE]...\nSearch for PATTERN in each FILE or standard input.\nPATTERN is, by default, a basic regular expression (BRE).\nExample: grep -i 'hello world' menu.h main.c\n\niwsvmbnHhqr\n\nRegexp selection and interpretation:\n  -i, --ignore-case         ignore case distinctions\n  -w, --word-regexp         force PATTERN to match only whole words\n\nMiscellaneous:\n  -s, --no-messages         suppress error messages\n  -v, --invert-match        select non-matching lines\n      --help                display this help and exit\n\nOutput control:\n  -n, --line-number         print line number with output lines\n  -H, --with-filename       print the file name for each match\n  -h, --no-filename         suppress the file name prefix on output\n  -q, --quiet, --silent     suppress all normal output\n  -r, --recursive           like --directories=recurse\n      --include <FILE_PATTERN>  search only files that match FILE_PATTERN\n\nWhen FILE is -, read standard input.  With no FILE, read . if a command-line\n-r is given, - otherwise.  If fewer than two FILEs are given, assume -h.\nExit status is 0 if any line is selected, 1 otherwise;\nif any error occurs and -q is not given, the exit status is 2.\n\nReport grep bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/kill.js b/dist/help/kill.js
new file mode 100755
index 0000000..ce76bf9
--- /dev/null
+++ b/dist/help/kill.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: kill [OPTION] pid | jobspec ... or kill -l [sigspec]\nSend a signal to a job.\n\nSend the processes identified by PID or JOBSPEC the signal named by\nSIGSPEC or SIGNUM.  If neither SIGSPEC nor SIGNUM is present, then\nSIGTERM is assumed.\n\n  -s sig         SIG is a signal name\n  -n sig         SIG is a signal number\n  -l [sigspec]   list the signal names; if arguments follow `-l' they\n                 are assumed to be signal numbers for which names\n                 should be listed\n      --help     display this help and exit\n\nExit status:\n  0   if OK,\n  1   if an invalid option is given or an error occurs.\n\nReport kill bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/ls.js b/dist/help/ls.js
new file mode 100755
index 0000000..7c154a0
--- /dev/null
+++ b/dist/help/ls.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs (the current directory by default).\nSort entries alphabetically if none of -tSU nor --sort is specified.\n\n  -a, --all                  do not ignore entries starting with .\n  -A, --almost-all           do not list implied . and ..\n  -d, --directory            list directory entries instead of contents,\n                               and do not dereference symbolic links\n  -f                         do not sort, enable -aU, disable -ls --color\n  -F, --classify             append indicator (one of */=>@|) to entries\n  -h, --human-readable       with -l, print sizes in human readable format\n  -i, --inode                print the index number of each file\n  -l                         use a long listing format\n  -q, --hide-control-chars   print ? instead of non graphic characters\n  -r, --reverse              reverse order while sorting\n  -R, --recursive            list subdirectories recursively\n  -S                         sort by file size\n  -t                         sort by modification time, newest first\n  -U                         do not sort; list entries in directory order\n  -w, --width=COLS           assume screen width instead of current value\n  -x                         list entries by lines instead of by columns\n  -1                         list one file per line\n      --help                 display this help and exit\n\nExit status:\n  0   if OK,\n  1   if minor problems (e.g., cannot access subdirectory),\n  2   if serious trouble (e.g., cannot access command-line argument).\n\nReport ls bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/mkdir.js b/dist/help/mkdir.js
new file mode 100755
index 0000000..6ffa2cd
--- /dev/null
+++ b/dist/help/mkdir.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mkdir [OPTION]... DIRECTORY...\nCreate the DIRECTORY(ies), if they do not already exist.\n\n  -p, --parents     no error if existing, make parent directories as needed\n  -v, --verbose     print a message for each created directory\n      --help        display this help and exit\n\nReport mkdir bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/mv.js b/dist/help/mv.js
new file mode 100755
index 0000000..a368bf1
--- /dev/null
+++ b/dist/help/mv.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mv [OPTION]... [-T] SOURCE DEST\n  or:  mv [OPTION]... SOURCE... DIRECTORY\n  or:  mv [OPTION]... -t DIRECTORY SOURCE...\nRename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n  -f, --force                  do not prompt before overwriting\n  -n, --no-clobber             do not overwrite an existing file\n      --striptrailingslashes   remove any trailing slashes from each SOURCE\n                                 argument\n  -v, --verbose                explain what is being done\n      --help                   display this help and exit\n\nIf you specify -f and -n, only -f takes effect.\n\nReport mv bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/pwd.js b/dist/help/pwd.js
new file mode 100755
index 0000000..2db3568
--- /dev/null
+++ b/dist/help/pwd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: pwd [-LP]\nPrint the name of the current working directory.\n\n      --help        display this help and exit\n\nExit status:\n  0   if OK,\n  1   if an invalid option is given or the current directory\n      cannot be read.\n\nReport pwd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/rm.js b/dist/help/rm.js
new file mode 100755
index 0000000..85b4474
--- /dev/null
+++ b/dist/help/rm.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: rm [OPTION]... FILE...\nRemove (unlink) the FILE(s).\n\n  -f, --force           ignore nonexistent files and arguments, never prompt\n  -r, -R, --recursive   remove directories and their contents recursively\n      --help            display this help and exit\n\nBy default, rm does not remove directories.  Use the --recursive (-r or -R)\noption to remove each listed directory, too, along with all of its contents.\n\nTo remove a file whose name starts with a '-', for example '-foo',\nuse one of these commands:\n  rm -- -foo\n  rm ./-foo\n\nNote that if you use rm to remove a file, it might be possible to recover\nsome of its contents, given sufficient expertise and/or time.\n\nReport rm bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/sort.js b/dist/help/sort.js
new file mode 100755
index 0000000..6e59482
--- /dev/null
+++ b/dist/help/sort.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: sort [OPTION]... [FILE]...\nWrite sorted concatenation of all FILE(s) to standard output.\n\nOrdering options:\n  -M, --month-sort            compare (unknown) < 'JAN' < ... < 'DEC'\n  -h, --human-numeric-sort    compare human readable numbers (e.g., 2K 1G)\n  -n, --numeric-sort          compare according to string numerical value\n  -R, --random-sort           sort by random hash of keys\n  -r, --reverse               reverse the result of comparisons\n\nOther options:\n  -c, --check,\n      --check=diagnose-first  check for sorted input; do not sort\n  -o, --output=FILE           write result to FILE instead of standard output\n      --help                  display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nReport sort bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/touch.js b/dist/help/touch.js
new file mode 100755
index 0000000..3f2d444
--- /dev/null
+++ b/dist/help/touch.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: touch [OPTION]... FILE...\nUpdate the access and modification times of each FILE to the current time.\n\nA FILE argument that does not exist is created empty, unless -c is\nsupplied.\n\n  -a                      change only the access time\n  -c, --no-create         do not create any files\n  -d, --date <STRING>     parse STRING and use it instead of current time\n  -m                      change only the modification time\n  -r, --reference <FILE>  use this file's times instead of current time\n      --time <WORD>       change the specified time:\n                            WORD is access, atime, or use: equivalent to -a\n                            WORD is modify or mtime: equivalent to -m\n      --help              display this help and exit\n\nReport touch bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/help/unalias.js b/dist/help/unalias.js
new file mode 100755
index 0000000..cc9f409
--- /dev/null
+++ b/dist/help/unalias.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: unalias [OPTION] name ...\nRemove each name from the list of defined aliases.\n\n  -a           remove all alias definitions\n      --help   display this help and exit\n\nExit status:\n  0   if OK,\n  1   if a name is not an existing alias.\n\nReport unalias bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
new file mode 100755
index 0000000..030054a
--- /dev/null
+++ b/dist/index.js
@@ -0,0 +1,185 @@
+'use strict';
+
+var _ = require('lodash');
+var os = require('os');
+var Vorpal = require('vorpal');
+
+var commands = require('./../commands.json');
+var help = require('./help');
+var interfacer = require('./util/interfacer');
+
+var cmds = undefined;
+
+var app = {
+
+  commands: commands.commands,
+
+  importedCommands: commands.importedCommands,
+
+  vorpal: new Vorpal(),
+
+  _cwd: process.cwd(),
+
+  _fatal: false,
+
+  export: function _export(str, cbk) {
+    cbk = cbk || function () {};
+    var options = {
+      fatal: app._fatal || false
+    };
+    // Hook stdin, execute the command and
+    // then return it all.
+    var intercept = require('./util/intercept');
+    var out = '';
+    var unhook = intercept(function (str) {
+      out += str + '\n';
+      return '';
+    });
+    app.vorpal.execSync(str, options);
+    unhook();
+    return String(out).replace(/\n$/, '');
+  },
+  load: function load() {
+    var self = this;
+    self.vorpal.api = {};
+    this.commands.forEach(function (cmd) {
+      if (self.importedCommands.indexOf(cmd) > -1) {
+        return;
+      }
+      try {
+        (function () {
+          var mod = require('./commands/' + cmd + '.js');
+          var help = undefined;
+          try {
+            help = require('./help/' + cmd + '.js');
+            help = String(help).replace(/^\n|\n$/g, '');
+          } catch (e) {
+            // .. whatever
+          }
+          self.vorpal.use(mod, {
+            parent: self
+          });
+          var cmdObj = self.vorpal.find(cmd);
+          if (cmdObj && help) {
+            /* istanbul ignore next */
+            cmdObj.help(function (args, cb) {
+              cb(help);
+            });
+          }
+        })();
+      } catch (e) {
+        /* istanbul ignore next */
+        self.vorpal.log('Error loading command ' + cmd + ': ', e);
+      }
+    });
+    this.importedCommands.forEach(function (cmd) {
+      try {
+        var mod = require('vorpal-' + cmd);
+        self.vorpal.use(mod, {
+          parent: self
+        });
+      } catch (e) {
+        /* istanbul ignore next */
+        self.vorpal.log('Error loading command ' + cmd + ': ', e);
+      }
+    });
+
+    // If we're running Windows, register
+    // process spawning for Windows child processes.
+    // If on Linux, just does registers the .catch command.
+    var windows = require('./windows');
+    windows.registerCommands(self);
+
+    var _loop = function _loop(cmd) {
+      if (app.vorpal.api.hasOwnProperty(cmd)) {
+        app.export[cmd] = function (args, options, callback) {
+          callback = callback || function () {};
+          options = options || {};
+          options.vorpal = app.vorpal;
+          return interfacer.call(this, {
+            command: app.vorpal.api[cmd],
+            args: args,
+            options: options,
+            callback: callback,
+            async: app.vorpal.api[cmd].async || false,
+            silent: true
+          });
+        };
+      }
+    };
+
+    for (var cmd in app.vorpal.api) {
+      _loop(cmd);
+    }
+
+    app.vorpal.history('cash').localStorage('cash').help(help);
+
+    app.vorpal.find('exit').action(function () {
+      /* istanbul ignore next */
+      process.exit(1);
+    });
+
+    // Load aliases
+    var all = undefined;
+    try {
+      all = JSON.parse(app.vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      /* istanbul ignore next */
+      all = [];
+      /* istanbul ignore next */
+      app.vorpal.localStorage.removeItem('aliases');
+    }
+    var aliases = {};
+    /* istanbul ignore next */
+    for (var i = 0; i < all.length; ++i) {
+      var item = app.vorpal.localStorage.getItem('alias|' + all[i]);
+      if (item !== undefined && item !== null) {
+        aliases[all[i]] = item;
+      }
+    }
+    app.vorpal._aliases = aliases;
+
+    // Override SIGINT to be ignored,
+    // and if the user is insistent, give
+    // a helpful message. The purpose of this
+    // is to give a full shell feel, not an
+    // application running over the shell.
+    // Skip this on linux, as its mainly
+    // for dev testing.
+    /* istanbul ignore next */
+    if (os.platform().indexOf('win') > -1) {
+      (function () {
+        var counter = 0;
+        setInterval(function () {
+          counter = counter > 0 ? 0 : counter;
+        }, 3000);
+        app.vorpal.sigint(function () {
+          counter++;
+          app.vorpal.ui.submit('');
+          if (counter > 5) {
+            app.vorpal.log('(to quit Cash, use the "exit" command)');
+            counter -= 10000;
+          }
+          return;
+        });
+      })();
+    }
+
+    app.export.vorpal = app.vorpal;
+    _.extend(app.export, cmds);
+    return this;
+  }
+};
+
+cmds = {
+  /* istanbul ignore next */
+
+  show: function show() {
+    /* istanbul ignore next */
+    app.vorpal.show();
+  }
+};
+
+app.load();
+
+module.exports = app.export;
\ No newline at end of file
diff --git a/dist/lib/sugar.js b/dist/lib/sugar.js
new file mode 100755
index 0000000..ffee6c5
--- /dev/null
+++ b/dist/lib/sugar.js
@@ -0,0 +1,747 @@
+"use strict";
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+/*
+ *  Sugar Library v1.4.1
+ *
+ *  Freely distributable and licensed under the MIT-style license.
+ *  Copyright (c) 2014 Andrew Plummer
+ *  http://sugarjs.com/
+ *
+ * ---------------------------- */
+/* istanbul ignore next */
+(function () {
+  function aa(a) {
+    return function () {
+      return a;
+    };
+  }
+  /* istanbul ignore next */
+  var m = Object,
+      p = Array,
+      q = RegExp,
+      r = Date,
+      s = String,
+      t = Number,
+      u = Math,
+      ba = "undefined" !== typeof global ? global : this,
+      v = m.prototype.toString,
+      da = m.prototype.hasOwnProperty,
+      ea = m.defineProperty && m.defineProperties,
+      fa = "function" === typeof q(),
+      ga = !("0" in new s("a")),
+      ia = {},
+      ja = /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,
+      w = "Boolean Number String Array Date RegExp Function".split(" "),
+      la = ka("boolean", w[0]),
+      y = ka("number", w[1]),
+      z = ka("string", w[2]),
+      A = ma(w[3]),
+      C = ma(w[4]),
+      D = ma(w[5]),
+      F = ma(w[6]);
+  /* istanbul ignore next */
+  function ma(a) {
+    var b = "Array" === a && p.isArray || function (b, d) {
+      return (d || v.call(b)) === "[object " + a + "]";
+    };return ia[a] = b;
+  }function ka(a, b) {
+    function c(c) {
+      return G(c) ? v.call(c) === "[object " + b + "]" : (typeof c === "undefined" ? "undefined" : _typeof(c)) === a;
+    }return ia[b] = c;
+  }
+  function na(a) {
+    a.SugarMethods || (oa(a, "SugarMethods", {}), H(a, !1, !0, { extend: function extend(b, c, d) {
+        H(a, !1 !== d, c, b);
+      }, sugarRestore: function sugarRestore() {
+        return pa(this, a, arguments, function (a, c, d) {
+          oa(a, c, d.method);
+        });
+      }, sugarRevert: function sugarRevert() {
+        return pa(this, a, arguments, function (a, c, d) {
+          d.existed ? oa(a, c, d.original) : delete a[c];
+        });
+      } }));
+  }function H(a, b, c, d) {
+    var e = b ? a.prototype : a;na(a);I(d, function (d, f) {
+      var h = e[d],
+          l = J(e, d);F(c) && h && (f = qa(h, f, c));!1 === c && h || oa(e, d, f);a.SugarMethods[d] = { method: f, existed: l, original: h, instance: b };
+    });
+  }
+  function K(a, b, c, d, e) {
+    var g = {};d = z(d) ? d.split(",") : d;d.forEach(function (a, b) {
+      e(g, a, b);
+    });H(a, b, c, g);
+  }function pa(a, b, c, d) {
+    var e = 0 === c.length,
+        g = L(c),
+        f = !1;I(b.SugarMethods, function (b, c) {
+      if (e || -1 !== g.indexOf(b)) f = !0, d(c.instance ? a.prototype : a, b, c);
+    });return f;
+  }function qa(a, b, c) {
+    return function (d) {
+      return c.apply(this, arguments) ? b.apply(this, arguments) : a.apply(this, arguments);
+    };
+  }function oa(a, b, c) {
+    ea ? m.defineProperty(a, b, { value: c, configurable: !0, enumerable: !1, writable: !0 }) : a[b] = c;
+  }
+  function L(a, b, c) {
+    var d = [];c = c || 0;var e;for (e = a.length; c < e; c++) {
+      d.push(a[c]), b && b.call(a, a[c], c);
+    }return d;
+  }function sa(a, b, c) {
+    var d = a[c || 0];A(d) && (a = d, c = 0);L(a, b, c);
+  }function ta(a) {
+    if (!a || !a.call) throw new TypeError("Callback is not callable");
+  }function M(a) {
+    return void 0 !== a;
+  }function N(a) {
+    return void 0 === a;
+  }function J(a, b) {
+    return !!a && da.call(a, b);
+  }function G(a) {
+    return !!a && ("object" === (typeof a === "undefined" ? "undefined" : _typeof(a)) || fa && D(a));
+  }function ua(a) {
+    var b = typeof a === "undefined" ? "undefined" : _typeof(a);return null == a || "string" === b || "number" === b || "boolean" === b;
+  }
+  function va(a, b) {
+    b = b || v.call(a);try {
+      if (a && a.constructor && !J(a, "constructor") && !J(a.constructor.prototype, "isPrototypeOf")) return !1;
+    } catch (c) {
+      return !1;
+    }return !!a && "[object Object]" === b && "hasOwnProperty" in a;
+  }function I(a, b) {
+    for (var c in a) {
+      if (J(a, c) && !1 === b.call(a, c, a[c], a)) break;
+    }
+  }function wa(a, b) {
+    for (var c = 0; c < a; c++) {
+      b(c);
+    }
+  }function xa(a, b) {
+    I(b, function (c) {
+      a[c] = b[c];
+    });return a;
+  }function ya(a) {
+    ua(a) && (a = m(a));if (ga && z(a)) for (var b = a, c = 0, d; d = b.charAt(c);) {
+      b[c++] = d;
+    }return a;
+  }function O(a) {
+    xa(this, ya(a));
+  }
+  O.prototype.constructor = m;var P = u.abs,
+      za = u.pow,
+      Aa = u.ceil,
+      Q = u.floor,
+      R = u.round,
+      Ca = u.min,
+      S = u.max;function Da(a, b, c) {
+    var d = za(10, P(b || 0));c = c || R;0 > b && (d = 1 / d);return c(a * d) / d;
+  }var Ea = 48,
+      Fa = 57,
+      Ga = 65296,
+      Ha = 65305,
+      Ia = ".",
+      Ja = "",
+      Ka = {},
+      La;function Ma() {
+    return "\t\n\u000b\f\r   ᠎             \u2028\u2029　﻿";
+  }function Na(a, b) {
+    var c = "";for (a = a.toString(); 0 < b;) {
+      if (b & 1 && (c += a), b >>= 1) a += a;
+    }return c;
+  }
+  function Oa(a, b) {
+    var c, d;c = a.replace(La, function (a) {
+      a = Ka[a];a === Ia && (d = !0);return a;
+    });return d ? parseFloat(c) : parseInt(c, b || 10);
+  }function T(a, b, c, d) {
+    d = P(a).toString(d || 10);d = Na("0", b - d.replace(/\.\d+/, "").length) + d;if (c || 0 > a) d = (0 > a ? "-" : "+") + d;return d;
+  }function Pa(a) {
+    if (11 <= a && 13 >= a) return "th";switch (a % 10) {case 1:
+        return "st";case 2:
+        return "nd";case 3:
+        return "rd";default:
+        return "th";}
+  }
+  function Qa(a, b) {
+    function c(a, c) {
+      if (a || -1 < b.indexOf(c)) d += c;
+    }var d = "";b = b || "";c(a.multiline, "m");c(a.ignoreCase, "i");c(a.global, "g");c(a.u, "y");return d;
+  }function Ra(a) {
+    z(a) || (a = s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g, "\\$1");
+  }function U(a, b) {
+    return a["get" + (a._utc ? "UTC" : "") + b]();
+  }function Sa(a, b, c) {
+    return a["set" + (a._utc && "ISOWeek" != b ? "UTC" : "") + b](c);
+  }
+  function Ta(a, b) {
+    var c = typeof a === "undefined" ? "undefined" : _typeof(a),
+        d,
+        e,
+        g,
+        f,
+        h,
+        l,
+        n;if ("string" === c) return a;g = v.call(a);d = va(a, g);e = A(a, g);if (null != a && d || e) {
+      b || (b = []);if (1 < b.length) for (l = b.length; l--;) {
+        if (b[l] === a) return "CYC";
+      }b.push(a);d = a.valueOf() + s(a.constructor);f = e ? a : m.keys(a).sort();l = 0;for (n = f.length; l < n; l++) {
+        h = e ? l : f[l], d += h + Ta(a[h], b);
+      }b.pop();
+    } else d = -Infinity === 1 / a ? "-0" : s(a && a.valueOf ? a.valueOf() : a);return c + g + d;
+  }function Ua(a, b) {
+    return a === b ? 0 !== a || 1 / a === 1 / b : Va(a) && Va(b) ? Ta(a) === Ta(b) : !1;
+  }
+  function Va(a) {
+    var b = v.call(a);return ja.test(b) || va(a, b);
+  }function Wa(a, b, c) {
+    var d,
+        e = a.length,
+        g = b.length,
+        f = !1 !== b[g - 1];if (!(g > (f ? 1 : 2))) return Xa(a, e, b[0], f, c);d = [];L(b, function (b) {
+      if (la(b)) return !1;d.push(Xa(a, e, b, f, c));
+    });return d;
+  }function Xa(a, b, c, d, e) {
+    d && (c %= b, 0 > c && (c = b + c));return e ? a.charAt(c) : a[c];
+  }function Ya(a, b) {
+    K(b, !0, !1, a, function (a, b) {
+      a[b + ("equal" === b ? "s" : "")] = function () {
+        return m[b].apply(null, [this].concat(L(arguments)));
+      };
+    });
+  }na(m);I(w, function (a, b) {
+    na(ba[b]);
+  });var Za, $a;
+  for ($a = 0; 9 >= $a; $a++) {
+    Za = s.fromCharCode($a + Ga), Ja += Za, Ka[Za] = s.fromCharCode($a + Ea);
+  }Ka[","] = "";Ka["．"] = Ia;Ka[Ia] = Ia;La = q("[" + Ja + "．," + Ia + "]", "g");
+  "use strict";H(m, !1, !1, { keys: function keys(a) {
+      var b = [];if (!G(a) && !D(a) && !F(a)) throw new TypeError("Object required");I(a, function (a) {
+        b.push(a);
+      });return b;
+    } });
+  function ab(a, b, c, d) {
+    var e = a.length,
+        g = -1 == d,
+        f = g ? e - 1 : 0;c = isNaN(c) ? f : parseInt(c >> 0);0 > c && (c = e + c);if (!g && 0 > c || g && c >= e) c = f;for (; g && 0 <= c || !g && c < e;) {
+      if (a[c] === b) return c;c += d;
+    }return -1;
+  }function bb(a, b, c, d) {
+    var e = a.length,
+        g = 0,
+        f = M(c);ta(b);if (0 != e || f) f || (c = a[d ? e - 1 : g], g++);else throw new TypeError("Reduce called on empty array with no initial value");for (; g < e;) {
+      f = d ? e - g - 1 : g, f in a && (c = b(c, a[f], f, a)), g++;
+    }return c;
+  }function cb(a) {
+    if (0 === a.length) throw new TypeError("First argument must be defined");
+  }H(p, !1, !1, { isArray: function isArray(a) {
+      return A(a);
+    } });
+  H(p, !0, !1, { every: function every(a, b) {
+      var c = this.length,
+          d = 0;for (cb(arguments); d < c;) {
+        if (d in this && !a.call(b, this[d], d, this)) return !1;d++;
+      }return !0;
+    }, some: function some(a, b) {
+      var c = this.length,
+          d = 0;for (cb(arguments); d < c;) {
+        if (d in this && a.call(b, this[d], d, this)) return !0;d++;
+      }return !1;
+    }, map: function map(a, b) {
+      b = arguments[1];var c = this.length,
+          d = 0,
+          e = Array(c);for (cb(arguments); d < c;) {
+        d in this && (e[d] = a.call(b, this[d], d, this)), d++;
+      }return e;
+    }, filter: function filter(a) {
+      var b = arguments[1],
+          c = this.length,
+          d = 0,
+          e = [];for (cb(arguments); d < c;) {
+        d in this && a.call(b, this[d], d, this) && e.push(this[d]), d++;
+      }return e;
+    }, indexOf: function indexOf(a, b) {
+      return z(this) ? this.indexOf(a, b) : ab(this, a, b, 1);
+    }, lastIndexOf: function lastIndexOf(a, b) {
+      return z(this) ? this.lastIndexOf(a, b) : ab(this, a, b, -1);
+    }, forEach: function forEach(a, b) {
+      var c = this.length,
+          d = 0;for (ta(a); d < c;) {
+        d in this && a.call(b, this[d], d, this), d++;
+      }
+    }, reduce: function reduce(a, b) {
+      return bb(this, a, b);
+    }, reduceRight: function reduceRight(a, b) {
+      return bb(this, a, b, !0);
+    } });
+  H(Function, !0, !1, { bind: function bind(a) {
+      var b = this,
+          c = L(arguments, null, 1),
+          d;if (!F(this)) throw new TypeError("Function.prototype.bind called on a non-function");d = function d() {
+        return b.apply(b.prototype && this instanceof b ? this : a, c.concat(L(arguments)));
+      };d.prototype = this.prototype;return d;
+    } });H(r, !1, !1, { now: function now() {
+      return new r().getTime();
+    } });
+  (function () {
+    var a = Ma().match(/^\s+$/);try {
+      s.prototype.trim.call([1]);
+    } catch (b) {
+      a = !1;
+    }H(s, !0, !a, { trim: function trim() {
+        return this.toString().trimLeft().trimRight();
+      }, trimLeft: function trimLeft() {
+        return this.replace(q("^[" + Ma() + "]+"), "");
+      }, trimRight: function trimRight() {
+        return this.replace(q("[" + Ma() + "]+$"), "");
+      } });
+  })();
+  (function () {
+    var a = new r(r.UTC(1999, 11, 31)),
+        a = a.toISOString && "1999-12-31T00:00:00.000Z" === a.toISOString();K(r, !0, !a, "toISOString,toJSON", function (a, c) {
+      a[c] = function () {
+        return T(this.getUTCFullYear(), 4) + "-" + T(this.getUTCMonth() + 1, 2) + "-" + T(this.getUTCDate(), 2) + "T" + T(this.getUTCHours(), 2) + ":" + T(this.getUTCMinutes(), 2) + ":" + T(this.getUTCSeconds(), 2) + "." + T(this.getUTCMilliseconds(), 3) + "Z";
+      };
+    });
+  })();
+  "use strict";
+  var W,
+      Ib,
+      Jb = "ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),
+      Kb = "({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",
+      Lb = {},
+      Mb,
+      Nb,
+      Ob,
+      Pb = [],
+      Qb = {},
+      X = { yyyy: function yyyy(a) {
+      return U(a, "FullYear");
+    }, yy: function yy(a) {
+      return U(a, "FullYear") % 100;
+    }, ord: function ord(a) {
+      a = U(a, "Date");return a + Pa(a);
+    }, tz: function tz(a) {
+      return a.getUTCOffset();
+    }, isotz: function isotz(a) {
+      return a.getUTCOffset(!0);
+    },
+    Z: function Z(a) {
+      return a.getUTCOffset();
+    }, ZZ: function ZZ(a) {
+      return a.getUTCOffset().replace(/(\d{2})$/, ":$1");
+    } },
+      Rb = [{ name: "year", method: "FullYear", k: !0, b: function b(a) {
+      return 864E5 * (365 + (a ? a.isLeapYear() ? 1 : 0 : 0.25));
+    } }, { name: "month", error: 0.919, method: "Month", k: !0, b: function b(a, _b) {
+      var c = 30.4375,
+          d;a && (d = a.daysInMonth(), _b <= d.days() && (c = d));return 864E5 * c;
+    } }, { name: "week", method: "ISOWeek", b: aa(6048E5) }, { name: "day", error: 0.958, method: "Date", k: !0, b: aa(864E5) }, { name: "hour", method: "Hours", b: aa(36E5) }, { name: "minute",
+    method: "Minutes", b: aa(6E4) }, { name: "second", method: "Seconds", b: aa(1E3) }, { name: "millisecond", method: "Milliseconds", b: aa(1) }],
+      Sb = {};function Tb(a) {
+    xa(this, a);this.g = Pb.concat();
+  }
+  Tb.prototype = { getMonth: function getMonth(a) {
+      return y(a) ? a - 1 : this.months.indexOf(a) % 12;
+    }, getWeekday: function getWeekday(a) {
+      return this.weekdays.indexOf(a) % 7;
+    }, addFormat: function addFormat(a, b, c, d, e) {
+      var g = c || [],
+          f = this,
+          h;a = a.replace(/\s+/g, "[,. ]*");a = a.replace(/\{([^,]+?)\}/g, function (a, b) {
+        var d,
+            e,
+            h,
+            B = b.match(/\?$/);h = b.match(/^(\d+)\??$/);var k = b.match(/(\d)(?:-(\d))?/),
+            E = b.replace(/[^a-z]+$/, "");h ? d = f.tokens[h[1]] : f[E] ? d = f[E] : f[E + "s"] && (d = f[E + "s"], k && (e = [], d.forEach(function (a, b) {
+          var c = b % (f.units ? 8 : d.length);c >= k[1] && c <= (k[2] || k[1]) && e.push(a);
+        }), d = e), d = Ub(d));h ? h = "(?:" + d + ")" : (c || g.push(E), h = "(" + d + ")");B && (h += "?");return h;
+      });b ? (b = Vb(f, e), e = ["t", "[\\s\\u3000]"].concat(f.timeMarker), h = a.match(/\\d\{\d,\d\}\)+\??$/), Wb(f, "(?:" + b + ")[,\\s\\u3000]+?" + a, Jb.concat(g), d), Wb(f, a + "(?:[,\\s]*(?:" + e.join("|") + (h ? "+" : "*") + ")" + b + ")?", g.concat(Jb), d)) : Wb(f, a, g, d);
+    } };
+  function Xb(a, b, c) {
+    var d,
+        e,
+        g = b[0],
+        f = b[1],
+        h = b[2];b = a[c] || a.relative;if (F(b)) return b.call(a, g, f, h, c);e = a.units[8 * (a.plural && 1 < g ? 1 : 0) + f] || a.units[f];a.capitalizeUnit && (e = Yb(e));d = a.modifiers.filter(function (a) {
+      return "sign" == a.name && a.value == (0 < h ? 1 : -1);
+    })[0];return b.replace(/\{(.*?)\}/g, function (a, b) {
+      switch (b) {case "num":
+          return g;case "unit":
+          return e;case "sign":
+          return d.src;}
+    });
+  }function Zb(a, b) {
+    b = b || a.code;return "en" === b || "en-US" === b ? !0 : a.variant;
+  }
+  function $b(a, b) {
+    return b.replace(q(a.num, "g"), function (b) {
+      return ac(a, b) || "";
+    });
+  }function ac(a, b) {
+    var c;return y(b) ? b : b && -1 !== (c = a.numbers.indexOf(b)) ? (c + 1) % 10 : 1;
+  }function Y(a, b) {
+    var c;z(a) || (a = "");c = Sb[a] || Sb[a.slice(0, 2)];if (!1 === b && !c) throw new TypeError("Invalid locale.");return c || Ib;
+  }
+  function bc(a, b) {
+    function c(a) {
+      var b = h[a];z(b) ? h[a] = b.split(",") : b || (h[a] = []);
+    }function d(a, b) {
+      a = a.split("+").map(function (a) {
+        return a.replace(/(.+):(.+)$/, function (a, b, c) {
+          return c.split("|").map(function (a) {
+            return b + a;
+          }).join("|");
+        });
+      }).join("|");a.split("|").forEach(b);
+    }function e(a, b, c) {
+      var e = [];h[a].forEach(function (a, f) {
+        b && (a += "+" + a.slice(0, 3));d(a, function (a, b) {
+          e[b * c + f] = a.toLowerCase();
+        });
+      });h[a] = e;
+    }function g(a, b, c) {
+      a = "\\d{" + a + "," + b + "}";c && (a += "|(?:" + Ub(h.numbers) + ")+");return a;
+    }function f(a, b) {
+      h[a] = h[a] || b;
+    }var h, l;h = new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l = !h.monthSuffix;e("months", l, 12);e("weekdays", l, 7);e("units", !1, 8);e("numbers", !1, 10);f("code", a);f("date", g(1, 2, h.digitDate));f("year", "'\\d{2}|" + g(4, 4));f("num", function () {
+      var a = ["-?\\d+"].concat(h.articles);h.numbers && (a = a.concat(h.numbers));return Ub(a);
+    }());(function () {
+      var a = [];h.i = {};h.modifiers.push({ name: "day", src: "yesterday", value: -1 });
+      h.modifiers.push({ name: "day", src: "today", value: 0 });h.modifiers.push({ name: "day", src: "tomorrow", value: 1 });h.modifiers.forEach(function (b) {
+        var c = b.name;d(b.src, function (d) {
+          var e = h[c];h.i[d] = b;a.push({ name: c, src: d, value: b.value });h[c] = e ? e + "|" + d : d;
+        });
+      });h.day += "|" + Ub(h.weekdays);h.modifiers = a;
+    })();h.monthSuffix && (h.month = g(1, 2), h.months = "1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function (a) {
+      return a + h.monthSuffix;
+    }));h.full_month = g(1, 2) + "|" + Ub(h.months);0 < h.timeSuffixes.length && h.addFormat(Vb(h), !1, Jb);
+    h.addFormat("{day}", !0);h.addFormat("{month}" + (h.monthSuffix || ""));h.addFormat("{year}" + (h.yearSuffix || ""));h.timeParse.forEach(function (a) {
+      h.addFormat(a, !0);
+    });h.dateParse.forEach(function (a) {
+      h.addFormat(a);
+    });return Sb[a] = h;
+  }function Wb(a, b, c, d) {
+    a.g.unshift({ r: d, locale: a, q: q("^" + b + "$", "i"), to: c });
+  }function Yb(a) {
+    return a.slice(0, 1).toUpperCase() + a.slice(1);
+  }function Ub(a) {
+    return a.filter(function (a) {
+      return !!a;
+    }).join("|");
+  }function cc() {
+    var a = r.SugarNewDate;return a ? a() : new r();
+  }
+  function dc(a, b) {
+    var c;if (G(a[0])) return a;if (y(a[0]) && !y(a[1])) return [a[0]];if (z(a[0]) && b) return [ec(a[0]), a[1]];c = {};Nb.forEach(function (b, e) {
+      c[b.name] = a[e];
+    });return [c];
+  }function ec(a) {
+    var b,
+        c = {};if (a = a.match(/^(\d+)?\s?(\w+?)s?$/i)) N(b) && (b = parseInt(a[1]) || 1), c[a[2].toLowerCase()] = b;return c;
+  }function fc(a, b, c) {
+    var d;N(c) && (c = Ob.length);for (b = b || 0; b < c && (d = Ob[b], !1 !== a(d.name, d, b)); b++) {}
+  }
+  function gc(a, b) {
+    var c = {},
+        d,
+        e;b.forEach(function (b, f) {
+      d = a[f + 1];N(d) || "" === d || ("year" === b && (c.t = d.replace(/'/, "")), e = parseFloat(d.replace(/'/, "").replace(/,/, ".")), c[b] = isNaN(e) ? d.toLowerCase() : e);
+    });return c;
+  }function hc(a) {
+    a = a.trim().replace(/^just (?=now)|\.+$/i, "");return ic(a);
+  }
+  function ic(a) {
+    return a.replace(Mb, function (a, c, d) {
+      var e = 0,
+          g = 1,
+          f,
+          h;if (c) return a;d.split("").reverse().forEach(function (a) {
+        a = Lb[a];var b = 9 < a;b ? (f && (e += g), g *= a / (h || 1), h = a) : (!1 === f && (g *= 10), e += g * a);f = b;
+      });f && (e += g);return e;
+    });
+  }
+  function jc(a, b, c, d) {
+    function e(a) {
+      vb.push(a);
+    }function g() {
+      vb.forEach(function (a) {
+        a.call();
+      });
+    }function f() {
+      var a = n.getWeekday();n.setWeekday(7 * (k.num - 1) + (a > Ba ? Ba + 7 : Ba));
+    }function h() {
+      var a = B.i[k.edge];fc(function (a) {
+        if (M(k[a])) return E = a, !1;
+      }, 4);if ("year" === E) k.e = "month";else if ("month" === E || "week" === E) k.e = "day";n[(0 > a.value ? "endOf" : "beginningOf") + Yb(E)]();-2 === a.value && n.reset();
+    }function l() {
+      var a;fc(function (b, c, d) {
+        "day" === b && (b = "date");if (M(k[b])) {
+          if (d >= wb) return n.setTime(NaN), !1;a = a || {};a[b] = k[b];
+          delete k[b];
+        }
+      });a && e(function () {
+        n.set(a, !0);
+      });
+    }var n, x, ha, vb, B, k, E, wb, Ba, ra, ca;n = cc();vb = [];n.utc(d);C(a) ? n.utc(a.isUTC()).setTime(a.getTime()) : y(a) ? n.setTime(a) : G(a) ? (n.set(a, !0), k = a) : z(a) && (ha = Y(b), a = hc(a), ha && I(ha.o ? [ha.o].concat(ha.g) : ha.g, function (c, d) {
+      var g = a.match(d.q);if (g) {
+        B = d.locale;k = gc(g, d.to);B.o = d;k.utc && n.utc();if (k.timestamp) return k = k.timestamp, !1;d.r && !z(k.month) && (z(k.date) || Zb(ha, b)) && (ca = k.month, k.month = k.date, k.date = ca);k.year && 2 === k.t.length && (k.year = 100 * R(U(cc(), "FullYear") / 100) - 100 * R(k.year / 100) + k.year);k.month && (k.month = B.getMonth(k.month), k.shift && !k.unit && (k.unit = B.units[7]));k.weekday && k.date ? delete k.weekday : k.weekday && (k.weekday = B.getWeekday(k.weekday), k.shift && !k.unit && (k.unit = B.units[5]));k.day && (ca = B.i[k.day]) ? (k.day = ca.value, n.reset(), x = !0) : k.day && -1 < (Ba = B.getWeekday(k.day)) && (delete k.day, k.num && k.month ? (e(f), k.day = 1) : k.weekday = Ba);k.date && !y(k.date) && (k.date = $b(B, k.date));k.ampm && k.ampm === B.ampm[1] && 12 > k.hour ? k.hour += 12 : k.ampm === B.ampm[0] && 12 === k.hour && (k.hour = 0);if ("offset_hours" in k || "offset_minutes" in k) n.utc(), k.offset_minutes = k.offset_minutes || 0, k.offset_minutes += 60 * k.offset_hours, "-" === k.offset_sign && (k.offset_minutes *= -1), k.minute -= k.offset_minutes;k.unit && (x = !0, ra = ac(B, k.num), wb = B.units.indexOf(k.unit) % 8, E = W.units[wb], l(), k.shift && (ra *= (ca = B.i[k.shift]) ? ca.value : 0), k.sign && (ca = B.i[k.sign]) && (ra *= ca.value), M(k.weekday) && (n.set({ weekday: k.weekday }, !0), delete k.weekday), k[E] = (k[E] || 0) + ra);k.edge && e(h);"-" === k.year_sign && (k.year *= -1);fc(function (a, b, c) {
+          b = k[a];var d = b % 1;d && (k[Ob[c - 1].name] = R(d * ("second" === a ? 1E3 : 60)), k[a] = Q(b));
+        }, 1, 4);return !1;
+      }
+    }), k ? x ? n.advance(k) : (n._utc && n.reset(), kc(n, k, !0, !1, c)) : ("now" !== a && (n = new r(a)), d && n.addMinutes(-n.getTimezoneOffset())), g(), n.utc(!1));return { c: n, set: k };
+  }function lc(a) {
+    var b,
+        c = P(a),
+        d = c,
+        e = 0;fc(function (a, f, h) {
+      b = Q(Da(c / f.b(), 1));1 <= b && (d = b, e = h);
+    }, 1);return [d, e, a];
+  }
+  function mc(a) {
+    var b = lc(a.millisecondsFromNow());if (6 === b[1] || 5 === b[1] && 4 === b[0] && a.daysFromNow() >= cc().daysInMonth()) b[0] = P(a.monthsFromNow()), b[1] = 6;return b;
+  }function nc(a, b, c) {
+    function d(a, c) {
+      var d = U(a, "Month");return Y(c).months[d + 12 * b];
+    }Z(a, d, c);Z(Yb(a), d, c, 1);
+  }function Z(a, b, c, d) {
+    X[a] = function (a, g) {
+      var f = b(a, g);c && (f = f.slice(0, c));d && (f = f.slice(0, d).toUpperCase() + f.slice(d));return f;
+    };
+  }
+  function oc(a, b, c) {
+    X[a] = b;X[a + a] = function (a, c) {
+      return T(b(a, c), 2);
+    };c && (X[a + a + a] = function (a, c) {
+      return T(b(a, c), 3);
+    }, X[a + a + a + a] = function (a, c) {
+      return T(b(a, c), 4);
+    });
+  }function pc(a) {
+    var b = a.match(/(\{\w+\})|[^{}]+/g);Qb[a] = b.map(function (a) {
+      a.replace(/\{(\w+)\}/, function (b, e) {
+        a = X[e] || e;return e;
+      });return a;
+    });
+  }
+  function qc(a, b, c, d) {
+    var e;if (!a.isValid()) return "Invalid Date";Date[b] ? b = Date[b] : F(b) && (e = mc(a), b = b.apply(a, e.concat(Y(d))));if (!b && c) return e = e || mc(a), 0 === e[1] && (e[1] = 1, e[0] = 1), a = Y(d), Xb(a, e, 0 < e[2] ? "future" : "past");b = b || "long";if ("short" === b || "long" === b || "full" === b) b = Y(d)[b];Qb[b] || pc(b);var g, f;e = "";b = Qb[b];g = 0;for (c = b.length; g < c; g++) {
+      f = b[g], e += F(f) ? f(a, d) : f;
+    }return e;
+  }
+  function rc(a, b, c, d, e) {
+    var g,
+        f,
+        h,
+        l = 0,
+        n = 0,
+        x = 0;g = jc(b, c, null, e);0 < d && (n = x = d, f = !0);if (!g.c.isValid()) return !1;if (g.set && g.set.e) {
+      Rb.forEach(function (b) {
+        b.name === g.set.e && (l = b.b(g.c, a - g.c) - 1);
+      });b = Yb(g.set.e);if (g.set.edge || g.set.shift) g.c["beginningOf" + b]();"month" === g.set.e && (h = g.c.clone()["endOf" + b]().getTime());!f && g.set.sign && "millisecond" != g.set.e && (n = 50, x = -50);
+    }f = a.getTime();b = g.c.getTime();h = sc(a, b, h || b + l);return f >= b - n && f <= h + x;
+  }
+  function sc(a, b, c) {
+    b = new r(b);a = new r(c).utc(a.isUTC());23 !== U(a, "Hours") && (b = b.getTimezoneOffset(), a = a.getTimezoneOffset(), b !== a && (c += (a - b).minutes()));return c;
+  }
+  function kc(a, b, c, d, e) {
+    function g(a) {
+      return M(b[a]) ? b[a] : b[a + "s"];
+    }function f(a) {
+      return M(g(a));
+    }var h;if (y(b) && d) b = { milliseconds: b };else if (y(b)) return a.setTime(b), a;M(b.date) && (b.day = b.date);fc(function (d, e, g) {
+      var l = "day" === d;if (f(d) || l && f("weekday")) return b.e = d, h = +g, !1;!c || "week" === d || l && f("week") || Sa(a, e.method, l ? 1 : 0);
+    });Rb.forEach(function (c) {
+      var e = c.name;c = c.method;var h;h = g(e);N(h) || (d ? ("week" === e && (h = (b.day || 0) + 7 * h, c = "Date"), h = h * d + U(a, c)) : "month" === e && f("day") && Sa(a, "Date", 15), Sa(a, c, h), d && "month" === e && (e = h, 0 > e && (e = e % 12 + 12), e % 12 != U(a, "Month") && Sa(a, "Date", 0)));
+    });d || f("day") || !f("weekday") || a.setWeekday(g("weekday"));var l;a: {
+      switch (e) {case -1:
+          l = a > cc();break a;case 1:
+          l = a < cc();break a;}l = void 0;
+    }l && fc(function (b, c) {
+      if ((c.k || "week" === b && f("weekday")) && !(f(b) || "day" === b && f("weekday"))) return a[c.j](e), !1;
+    }, h + 1);return a;
+  }
+  function Vb(a, b) {
+    var c = Kb,
+        d = { h: 0, m: 1, s: 2 },
+        e;a = a || W;return c.replace(/{([a-z])}/g, function (c, f) {
+      var h = [],
+          l = "h" === f,
+          n = l && !b;if ("t" === f) return a.ampm.join("|");l && h.push(":");(e = a.timeSuffixes[d[f]]) && h.push(e + "\\s*");return 0 === h.length ? "" : "(?:" + h.join("|") + ")" + (n ? "" : "?");
+    });
+  }function tc(a, b, c) {
+    var d, e;y(a[1]) ? d = dc(a)[0] : (d = a[0], e = a[1]);return jc(d, e, b, c).c;
+  }
+  H(r, !1, !0, { create: function create() {
+      return tc(arguments);
+    }, past: function past() {
+      return tc(arguments, -1);
+    }, future: function future() {
+      return tc(arguments, 1);
+    }, addLocale: function addLocale(a, b) {
+      return bc(a, b);
+    }, setLocale: function setLocale(a) {
+      var b = Y(a, !1);Ib = b;a && a != b.code && (b.code = a);return b;
+    }, getLocale: function getLocale(a) {
+      return a ? Y(a, !1) : Ib;
+    }, addFormat: function addFormat(a, b, c) {
+      Wb(Y(c), a, b);
+    } });
+  H(r, !0, !0, { set: function set() {
+      var a = dc(arguments);return kc(this, a[0], a[1]);
+    }, setWeekday: function setWeekday(a) {
+      if (!N(a)) return Sa(this, "Date", U(this, "Date") + a - U(this, "Day"));
+    }, setISOWeek: function setISOWeek(a) {
+      var b = U(this, "Day") || 7;if (!N(a)) return this.set({ month: 0, date: 4 }), this.set({ weekday: 1 }), 1 < a && this.addWeeks(a - 1), 1 !== b && this.advance({ days: b - 1 }), this.getTime();
+    }, getISOWeek: function getISOWeek() {
+      var a;a = this.clone();var b = U(a, "Day") || 7;a.addDays(4 - b).reset();return 1 + Q(a.daysSince(a.clone().beginningOfYear()) / 7);
+    }, beginningOfISOWeek: function beginningOfISOWeek() {
+      var a = this.getDay();0 === a ? a = -6 : 1 !== a && (a = 1);this.setWeekday(a);return this.reset();
+    }, endOfISOWeek: function endOfISOWeek() {
+      0 !== this.getDay() && this.setWeekday(7);return this.endOfDay();
+    }, getUTCOffset: function getUTCOffset(a) {
+      var b = this._utc ? 0 : this.getTimezoneOffset(),
+          c = !0 === a ? ":" : "";return !b && a ? "Z" : T(Q(-b / 60), 2, !0) + c + T(P(b % 60), 2);
+    }, utc: function utc(a) {
+      oa(this, "_utc", !0 === a || 0 === arguments.length);return this;
+    }, isUTC: function isUTC() {
+      return !!this._utc || 0 === this.getTimezoneOffset();
+    }, advance: function advance() {
+      var a = dc(arguments, !0);return kc(this, a[0], a[1], 1);
+    }, rewind: function rewind() {
+      var a = dc(arguments, !0);return kc(this, a[0], a[1], -1);
+    }, isValid: function isValid() {
+      return !isNaN(this.getTime());
+    }, isAfter: function isAfter(a, b) {
+      return this.getTime() > r.create(a).getTime() - (b || 0);
+    }, isBefore: function isBefore(a, b) {
+      return this.getTime() < r.create(a).getTime() + (b || 0);
+    }, isBetween: function isBetween(a, b, c) {
+      var d = this.getTime();a = r.create(a).getTime();var e = r.create(b).getTime();b = Ca(a, e);a = S(a, e);c = c || 0;return b - c < d && a + c > d;
+    }, isLeapYear: function isLeapYear() {
+      var a = U(this, "FullYear");return 0 === a % 4 && 0 !== a % 100 || 0 === a % 400;
+    },
+    daysInMonth: function daysInMonth() {
+      return 32 - U(new r(U(this, "FullYear"), U(this, "Month"), 32), "Date");
+    }, format: function format(a, b) {
+      return qc(this, a, !1, b);
+    }, relative: function relative(a, b) {
+      z(a) && (b = a, a = null);return qc(this, a, !0, b);
+    }, is: function is(a, b, c) {
+      var d, e;if (this.isValid()) {
+        if (z(a)) switch (a = a.trim().toLowerCase(), e = this.clone().utc(c), !0) {case "future" === a:
+            return this.getTime() > cc().getTime();case "past" === a:
+            return this.getTime() < cc().getTime();case "weekday" === a:
+            return 0 < U(e, "Day") && 6 > U(e, "Day");case "weekend" === a:
+            return 0 === U(e, "Day") || 6 === U(e, "Day");case -1 < (d = W.weekdays.indexOf(a) % 7):
+            return U(e, "Day") === d;case -1 < (d = W.months.indexOf(a) % 12):
+            return U(e, "Month") === d;}return rc(this, a, null, b, c);
+      }
+    }, reset: function reset(a) {
+      var b = {},
+          c;a = a || "hours";"date" === a && (a = "days");c = Rb.some(function (b) {
+        return a === b.name || a === b.name + "s";
+      });b[a] = a.match(/^days?/) ? 1 : 0;return c ? this.set(b, !0) : this;
+    }, clone: function clone() {
+      var a = new r(this.getTime());a.utc(!!this._utc);return a;
+    } });
+  H(r, !0, !0, { iso: function iso() {
+      return this.toISOString();
+    }, getWeekday: r.prototype.getDay, getUTCWeekday: r.prototype.getUTCDay });function uc(a, b) {
+    function c() {
+      return R(this * b);
+    }function d() {
+      return tc(arguments)[a.j](this);
+    }function e() {
+      return tc(arguments)[a.j](-this);
+    }var g = a.name,
+        f = {};f[g] = c;f[g + "s"] = c;f[g + "Before"] = e;f[g + "sBefore"] = e;f[g + "Ago"] = e;f[g + "sAgo"] = e;f[g + "After"] = d;f[g + "sAfter"] = d;f[g + "FromNow"] = d;f[g + "sFromNow"] = d;t.extend(f);
+  }H(t, !0, !0, { duration: function duration(a) {
+      a = Y(a);return Xb(a, lc(this), "duration");
+    } });
+  W = Ib = r.addLocale("en", { plural: !0, timeMarker: "at", ampm: "am,pm", months: "January,February,March,April,May,June,July,August,September,October,November,December", weekdays: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", units: "millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s", numbers: "one,two,three,four,five,six,seven,eight,nine,ten", articles: "a,an,the", tokens: "the,st|nd|rd|th,of", "short": "{Month} {d}, {yyyy}", "long": "{Month} {d}, {yyyy} {h}:{mm}{tt}", full: "{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
+    past: "{num} {unit} {sign}", future: "{num} {unit} {sign}", duration: "{num} {unit}", modifiers: [{ name: "sign", src: "ago|before", value: -1 }, { name: "sign", src: "from now|after|from|in|later", value: 1 }, { name: "edge", src: "last day", value: -2 }, { name: "edge", src: "end", value: -1 }, { name: "edge", src: "first day|beginning", value: 1 }, { name: "shift", src: "last", value: -1 }, { name: "shift", src: "the|this", value: 0 }, { name: "shift", src: "next", value: 1 }], dateParse: ["{month} {year}", "{shift} {unit=5-7}", "{0?} {date}{1}", "{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
+    timeParse: "{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";") });Ob = Rb.concat().reverse();Nb = Rb.concat();Nb.splice(2, 1);
+  K(r, !0, !0, Rb, function (a, b, c) {
+    function d(a) {
+      a /= f;var c = a % 1,
+          d = b.error || 0.999;c && P(c % 1) > d && (a = R(a));return 0 > a ? Aa(a) : Q(a);
+    }var e = b.name,
+        g = Yb(e),
+        f = b.b(),
+        h,
+        l;b.j = "add" + g + "s";h = function h(a, b) {
+      return d(this.getTime() - r.create(a, b).getTime());
+    };l = function l(a, b) {
+      return d(r.create(a, b).getTime() - this.getTime());
+    };a[e + "sAgo"] = l;a[e + "sUntil"] = l;a[e + "sSince"] = h;a[e + "sFromNow"] = h;a[b.j] = function (a, b) {
+      var c = {};c[e] = a;return this.advance(c, b);
+    };uc(b, f);3 > c && ["Last", "This", "Next"].forEach(function (b) {
+      a["is" + b + g] = function () {
+        return rc(this, b + " " + e, "en");
+      };
+    });4 > c && (a["beginningOf" + g] = function () {
+      var a = {};switch (e) {case "year":
+          a.year = U(this, "FullYear");break;case "month":
+          a.month = U(this, "Month");break;case "day":
+          a.day = U(this, "Date");break;case "week":
+          a.weekday = 0;}return this.set(a, !0);
+    }, a["endOf" + g] = function () {
+      var a = { hours: 23, minutes: 59, seconds: 59, milliseconds: 999 };switch (e) {case "year":
+          a.month = 11;a.day = 31;break;case "month":
+          a.day = this.daysInMonth();break;case "week":
+          a.weekday = 6;}return this.set(a, !0);
+    });
+  });
+  W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?", !0, ["year_sign", "year", "month", "date"], !1, !0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?", !0, ["date", "month", "year"], !0);W.addFormat("{full_month}[-.](\\d{4,4})", !1, ["month", "year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/", !1, ["timestamp"]);W.addFormat(Vb(W), !1, Jb);Pb = W.g.slice(0, 7).reverse();W.g = W.g.slice(7).concat(Pb);oc("f", function (a) {
+    return U(a, "Milliseconds");
+  }, !0);
+  oc("s", function (a) {
+    return U(a, "Seconds");
+  });oc("m", function (a) {
+    return U(a, "Minutes");
+  });oc("h", function (a) {
+    return U(a, "Hours") % 12 || 12;
+  });oc("H", function (a) {
+    return U(a, "Hours");
+  });oc("d", function (a) {
+    return U(a, "Date");
+  });oc("M", function (a) {
+    return U(a, "Month") + 1;
+  });(function () {
+    function a(a, c) {
+      var d = U(a, "Hours");return Y(c).ampm[Q(d / 12)] || "";
+    }Z("t", a, 1);Z("tt", a);Z("T", a, 1, 1);Z("TT", a, null, 2);
+  })();
+  /* istanbul ignore next */
+  (function () {
+    function a(a, c) {
+      var d = U(a, "Day");return Y(c).weekdays[d];
+    }Z("dow", a, 3);Z("Dow", a, 3, 1);Z("weekday", a);Z("Weekday", a, null, 1);
+  })();nc("mon", 0, 3);nc("month", 0);nc("month2", 1);nc("month3", 2);X.ms = X.f;X.milliseconds = X.f;X.seconds = X.s;X.minutes = X.m;X.hours = X.h;X["24hr"] = X.H;X["12hr"] = X.h;X.date = X.d;X.day = X.d;X.year = X.yyyy;K(r, !0, !0, "short,long,full", function (a, b) {
+    a[b] = function (a) {
+      return qc(this, b, !1, a);
+    };
+  });
+  "〇一二三四五六七八九十百千万".split("").forEach(function (a, b) {
+    9 < b && (b = za(10, b - 9));Lb[a] = b;
+  });xa(Lb, Ka);Mb = q("([期週周])?([〇一二三四五六七八九十百千万" + Ja + "]+)(?!昨)", "g");
+  /* istanbul ignore next */
+  (function () {
+    var a = W.weekdays.slice(0, 7),
+        b = W.months.slice(0, 12);K(r, !0, !0, "today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b), function (a, b) {
+      a["is" + Yb(b)] = function (a) {
+        return this.is(b, 0, a);
+      };
+    });
+  })();r.utc || (r.utc = { create: function create() {
+      return tc(arguments, 0, !0);
+    }, past: function past() {
+      return tc(arguments, -1, !0);
+    }, future: function future() {
+      return tc(arguments, 1, !0);
+    } });
+  H(r, !1, !0, { RFC1123: "{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}", RFC1036: "{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}", ISO8601_DATE: "{yyyy}-{MM}-{dd}", ISO8601_DATETIME: "{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}" });
+})();
\ No newline at end of file
diff --git a/dist/util/colorFile.js b/dist/util/colorFile.js
new file mode 100755
index 0000000..2368f96
--- /dev/null
+++ b/dist/util/colorFile.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+var chalk = {};
+var map = { cyan: 36, red: 31, magenta: 35 };
+Object.keys(map).forEach(function (key, value) {
+  chalk[key] = function (str) {
+    return '\u001b[' + value + 'm' + str + '\u001b[39m';
+  };
+});
+
+/**
+ * Wraps file strings in ANSI colors
+ * based on their extension.
+ *
+ * @param {file} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (file) {
+  var audio = ['aac', 'au', 'flac', 'mid', 'midi', 'mka', 'mp3', 'mpc', 'ogg', 'ra', 'wav', 'axa', 'oga', 'spx', 'xspf'];
+  var archive = ['tar', 'tgz', 'arj', 'taz', 'lzh', 'lzma', 'tlz', 'txz', 'zip', 'z', 'Z', 'dz', 'gz', 'lz', 'xz', 'bz2', 'bz', 'tbz', 'tbz2', 'tz', 'deb', 'rpm', 'jar', 'rar', 'ace', 'zoo', 'cpio', '7z', 'rz'];
+  var images = ['jpg', 'jpeg', 'gif', 'bmp', 'pbm', 'pgm', 'ppm', 'tga', 'xbm', 'xpm', 'tif', 'tiff', 'png', 'svg', 'svgz', 'mng', 'pcx', 'mov', 'mpg', 'mpeg', 'm2v', 'mkv', 'ogm', 'mp4', 'm4v', 'mp4v', 'vob', 'qt', 'nuv', 'wmv', 'asf', 'rm', 'rmvb', 'flc', 'avi', 'fli', 'flv', 'gl', 'dl', 'xcf', 'xwd', 'yuv', 'cgm', 'emf', 'axv', 'anx', 'ogv', 'ogx'];
+
+  var extension = String(file).toLowerCase().trim().split('.');
+  extension = extension[extension.length - 1];
+
+  var colored = strip(file);
+  colored = audio.indexOf(extension) > -1 ? chalk.cyan(file) : archive.indexOf(extension) > -1 ? chalk.red(file) : images.indexOf(extension) > -1 ? chalk.magenta(file) : colored;
+
+  return colored;
+};
\ No newline at end of file
diff --git a/dist/util/columnify.js b/dist/util/columnify.js
new file mode 100755
index 0000000..6f5a46e
--- /dev/null
+++ b/dist/util/columnify.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+var pad = require('./pad');
+
+/**
+ * Formats an array to display in a TTY
+ * in a pretty fashion.
+ *
+ * @param {Array} arr
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (arr, options) {
+  arr = arr || [];
+  options = options || {};
+  var bk = JSON.parse(JSON.stringify(arr));
+  var width = options.width && !isNaN(options.width) ? options.width : process.stdout.columns;
+  var longest = strip(bk.sort(function (a, b) {
+    return strip(b).length - strip(a).length;
+  })[0] || '').length + 2;
+  var fullWidth = strip(arr.join('')).length;
+  var fitsOneLine = fullWidth + arr.length * 2 <= width;
+  var cols = Math.floor(width / longest);
+  cols = cols < 1 ? 1 : cols;
+  if (fitsOneLine) {
+    return arr.join('  ');
+  }
+  var col = 0;
+  var lines = [];
+  var line = '';
+  for (var i = 0; i < arr.length; ++i) {
+    if (col < cols) {
+      col++;
+    } else {
+      if (String(strip(line)).trim() !== '') {
+        lines.push(line);
+      }
+      line = '';
+      col = 1;
+    }
+    if (cols === 1) {
+      // If we have files so damn
+      // long that we wrap, don't pad
+      // the lines.
+      line += arr[i];
+    } else {
+      // Pad the lines based on the
+      // longest word.
+      line += pad(arr[i], longest, ' ');
+    }
+  }
+  if (line !== '') {
+    lines.push(line);
+  }
+  return lines.join('\n');
+};
\ No newline at end of file
diff --git a/dist/util/converter.date.js b/dist/util/converter.date.js
new file mode 100755
index 0000000..17b2b52
--- /dev/null
+++ b/dist/util/converter.date.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * Date conversion utilities
+ */
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(num, padding) {
+  padding = padding || '0';
+  num = parseFloat(num);
+  if (num < 10) {
+    return '' + padding + num;
+  }
+  return num;
+}
+
+module.exports = {
+  unix: function unix(dt) {
+    var date = dt;
+    var day = pad(date.getDate(), ' ');
+    var month = months[date.getMonth()];
+    var hour = pad(date.getHours());
+    var min = pad(date.getMinutes());
+    var hourMin = hour + ':' + min;
+    day = day.length === 1 ? ' ' + day : day;
+    date = month + ' ' + day + ' ' + hourMin;
+    return date;
+  }
+};
\ No newline at end of file
diff --git a/dist/util/converter.path.js b/dist/util/converter.path.js
new file mode 100755
index 0000000..54ed700
--- /dev/null
+++ b/dist/util/converter.path.js
@@ -0,0 +1,19 @@
+'use strict';
+
+var path = require('path');
+
+/**
+ * Path conversion utilities
+ */
+
+module.exports = {
+  unix: function unix(str) {
+    var input = path.normalize(str);
+    input = input.replace(/\\/g, '\/');
+    var parts = input.split(':');
+    var drive = parts.shift();
+    var isLetter = drive.length === 1 && drive.match(/[a-z]/i);
+    var result = isLetter ? drive + parts.join(':') : input;
+    return result;
+  }
+};
\ No newline at end of file
diff --git a/dist/util/converter.permissions.js b/dist/util/converter.permissions.js
new file mode 100755
index 0000000..6cbe2f2
--- /dev/null
+++ b/dist/util/converter.permissions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+/**
+ * Permission conversion utilities
+ */
+
+module.exports = {
+
+  listing: {
+    0: '---',
+    1: '--x',
+    2: '-w-',
+    3: '-wx',
+    4: 'r--',
+    5: 'r-x',
+    6: 'rw-',
+    7: 'rwx'
+  },
+
+  modeToRWX: function modeToRWX(mode) {
+    var octal = this.modeToOctal(mode);
+    var rwx = this.octalToRWX(octal);
+    return rwx;
+  },
+  modeToOctal: function modeToOctal(mode) {
+    var octal = '0' + (mode & 511).toString(8);
+    return octal;
+  },
+  octalToRWX: function octalToRWX(octal) {
+    if (!octal) {
+      return undefined;
+    }
+    var list = this.listing;
+    var a = list[String(octal).charAt(1)];
+    var b = list[String(octal).charAt(2)];
+    var c = list[String(octal).charAt(3)];
+    return a + b + c;
+  }
+};
\ No newline at end of file
diff --git a/dist/util/expand.js b/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/dist/util/fetch.js b/dist/util/fetch.js
new file mode 100755
index 0000000..da862df
--- /dev/null
+++ b/dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+  files = files || [];
+  stdin = stdin !== undefined ? stdin : [];
+  var f = expand(files);
+
+  if (!(f.length === 0 && files.length > 0)) {
+    files = f;
+  }
+
+  for (var i = 0; i < files.length; ++i) {
+    try {
+      var stat = fs.statSync(files[i]);
+      if (stat.isDirectory()) {
+        files[i] = options.onDirectory(files[i]);
+      } else {
+        files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+      }
+    } catch (e) {
+      files[i] = options.onInvalidFile(files[i]);
+    }
+  }
+
+  var agg = files.length < 1 ? stdin : files;
+  var final = [];
+
+  for (var i = 0; i < agg.length; ++i) {
+    if (agg[i] !== undefined) {
+      final.push(agg[i]);
+    }
+  }
+  return final;
+};
\ No newline at end of file
diff --git a/dist/util/fileFromPath.js b/dist/util/fileFromPath.js
new file mode 100755
index 0000000..0583f23
--- /dev/null
+++ b/dist/util/fileFromPath.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * Parses a path and returns just the file
+ *
+ * @param {path} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (path) {
+  var fileShort = String(path).split('/');
+  fileShort = fileShort[fileShort.length - 1];
+  fileShort = fileShort.split('\\');
+  fileShort = fileShort[fileShort.length - 1];
+  return fileShort;
+};
\ No newline at end of file
diff --git a/dist/util/intercept.js b/dist/util/intercept.js
new file mode 100755
index 0000000..41ab014
--- /dev/null
+++ b/dist/util/intercept.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var _ = require('lodash');
+
+/**
+ * Intercepts stdout, passes thru callback
+ * also pass console.error thru stdout so it goes to callback too
+ * (stdout.write and stderr.write are both refs to the same stream.write function)
+ * returns an unhook() function, call when done intercepting
+ *
+ * @param {Function} callback
+ * @return {Function}
+ */
+
+module.exports = function (callback) {
+  var oldStdoutWrite = process.stdout.write;
+  var oldConsoleError = console.error;
+  process.stdout.write = function (write) {
+    return function (string) {
+      var args = _.toArray(arguments);
+      args[0] = interceptor(string);
+      write.apply(process.stdout, args);
+    };
+  }(process.stdout.write);
+
+  console.error = function () {
+    return function () {
+      var args = _.toArray(arguments);
+      args.unshift('\x1b[31m[ERROR]\x1b[0m');
+      console.log.apply(console.log, args);
+    };
+  }(console.error);
+
+  function interceptor(string) {
+    // only intercept the string
+    var result = callback(string);
+    if (typeof result === 'string') {
+      string = result.replace(/\n$/, '') + (result && /\n$/.test(string) ? '\n' : '');
+    }
+    return string;
+  }
+  // puts back to original
+  return function unhook() {
+    process.stdout.write = oldStdoutWrite;
+    console.error = oldConsoleError;
+  };
+};
\ No newline at end of file
diff --git a/dist/util/interfacer.js b/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/dist/util/lpad.js b/dist/util/lpad.js
new file mode 100755
index 0000000..61d8da7
--- /dev/null
+++ b/dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  var len = Math.max(0, width - strip(str).length);
+  return Array(len + 1).join(delimiter) + str;
+};
\ No newline at end of file
diff --git a/dist/util/pad.js b/dist/util/pad.js
new file mode 100755
index 0000000..b6eaeb7
--- /dev/null
+++ b/dist/util/pad.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads a value with with space or
+ * a specified delimiter to match a
+ * given width.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  var len = Math.max(0, width - strip(str).length);
+  return str + Array(len + 1).join(delimiter);
+};
\ No newline at end of file
diff --git a/dist/util/stripAnsi.js b/dist/util/stripAnsi.js
new file mode 100755
index 0000000..e05149e
--- /dev/null
+++ b/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+  var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+  return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
\ No newline at end of file
diff --git a/dist/util/unlinkSync.js b/dist/util/unlinkSync.js
new file mode 100755
index 0000000..784fb7d
--- /dev/null
+++ b/dist/util/unlinkSync.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var fs = require('fs');
+
+/**
+ * Normalizes _unlinkSync() across
+ * platforms to match Unix behavior, i.e.
+ * file can be unlinked even its it's
+ * read only.
+ * See https://github.com/joyent/node/issues/3006
+ *
+ * @param {String} file
+ * @api public
+ */
+
+module.exports = function (file) {
+  try {
+    fs.unlinkSync(file);
+  } catch (e) {
+    // Try to override file permission
+    /* istanbul ignore if */
+    if (e.code === 'EPERM') {
+      fs.chmodSync(file, '0666');
+      fs.unlinkSync(file);
+    } else {
+      /* istanbul ignore next */
+      throw e;
+    }
+  }
+};
\ No newline at end of file
diff --git a/dist/util/walkDir.js b/dist/util/walkDir.js
new file mode 100755
index 0000000..bfeabc2
--- /dev/null
+++ b/dist/util/walkDir.js
@@ -0,0 +1,41 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Walks a single directory calling
+ * a callback function for each file or
+ * folder, returning the path and results
+ * of fs.statSync.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  function readFile(path, cbk) {
+    var stat = undefined;
+    try {
+      stat = fs.statSync(path);
+      if (stat.isFile() || stat.isDirectory()) {
+        cbk(path, stat);
+      }
+    } catch (e) {
+      // .. if we can't read the file, forget
+      // about it for now.
+    }
+  }
+  try {
+    var dirs = fs.readdirSync(currentDirPath);
+    dirs.forEach(function (name) {
+      var filePath = path.join(currentDirPath, name);
+      readFile(filePath, callback);
+    });
+  } catch (e) {
+    if (e.code === 'ENOTDIR') {
+      readFile(currentDirPath, callback);
+    }
+  }
+};
\ No newline at end of file
diff --git a/dist/util/walkDirRecursive.js b/dist/util/walkDirRecursive.js
new file mode 100755
index 0000000..bc4be6d
--- /dev/null
+++ b/dist/util/walkDirRecursive.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Recursively walks through and executes
+ * a callback function for each directory found.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  fs.readdirSync(currentDirPath).forEach(function (name) {
+    var filePath = path.join(currentDirPath, name);
+    var stat = fs.statSync(filePath);
+    if (stat.isDirectory()) {
+      callback(filePath, stat);
+      module.exports(filePath, callback);
+    }
+  });
+};
\ No newline at end of file
diff --git a/dist/windows.js b/dist/windows.js
new file mode 100755
index 0000000..e4b52d9
--- /dev/null
+++ b/dist/windows.js
@@ -0,0 +1,120 @@
+'use strict';
+
+var _ = require('lodash');
+var os = require('os');
+
+var commands = require('./../commands.json').windowsCommands;
+
+module.exports = {
+  registerCommands: function registerCommands(self) {
+    self.vorpal.catch('[words...]', 'Catches content').parse(function (input) {
+      // Look for aliases and translate them.
+      // Makes cash.alias and cash.unalias work.
+      var parts = String(input).split(' ');
+      var first = parts.shift();
+      var out = input;
+      var translation = self.vorpal._aliases[first];
+      if (self.vorpal._aliases && translation) {
+        /* istanbul ignore next */
+        out = translation + ' ' + parts.join(' ');
+      }
+      return out;
+    })
+    /* istanbul ignore next */
+    .autocomplete(function () {
+      /* istanbul ignore next */
+      return _.map(self.vorpal.commands, '_name');
+    }).action(function (args, cb) {
+      cb = cb || function () {};
+      var spawn = require('child_process').spawn;
+      var slf = this;
+
+      var words = args.words.join(' ');
+      var argus = undefined;
+
+      var cmd = undefined;
+      // Only register commands if on Windows.
+      /* istanbul ignore next */
+      if (os.platform() === 'win32') {
+        for (var i = 0; i < commands.length; ++i) {
+          if (String(words.slice(0, commands[i].length)).toLowerCase() === commands[i].toLowerCase()) {
+            cmd = commands[i];
+            argus = String(words.slice(commands[i].length, words.length)).trim().split(' ');
+            argus = argus.length === 1 && argus[0] === '' ? [] : argus;
+          }
+        }
+      }
+
+      // Accommodate tests for Linux.
+      if (words === 'cash-test') {
+        cmd = 'echo';
+        argus = ['hi'];
+      }
+
+      if (cmd === undefined || argus === undefined) {
+        slf.help();
+        cb();
+        return;
+      }
+
+      argus.unshift(cmd);
+      argus.unshift('/C');
+      var proc = undefined;
+      var out = '';
+      try {
+        proc = spawn('cmd', argus);
+      } catch (e) {
+        /* istanbul ignore next */
+        slf.log(e);
+      }
+
+      var closed = false;
+
+      // Properly print stdout as it's fed,
+      // waiting for line breaks before sending
+      // it to Vorpal.
+      function print() {
+        var parts = String(out).split('\n');
+        /* istanbul ignore next */
+        if (parts.length > 1) {
+          out = parts.pop();
+          var logging = String(parts.join('\n')).replace(/\r\r/g, '\r');
+          slf.log(logging);
+        }
+        /* istanbul ignore next */
+        if (closed === false) {
+          setTimeout(function () {
+            print();
+          }, 50);
+        }
+      }
+      print();
+
+      /* istanbul ignore next */
+      proc.stdout.on('data', function (data) {
+        out += data.toString('utf8');
+      });
+
+      /* istanbul ignore next */
+      proc.stderr.on('data', function (data) {
+        out += data.toString('utf8');
+      });
+
+      proc.on('close', function () {
+        closed = true;
+        if (String(out).trim() !== '') {
+          slf.log(String(out).replace(/\r\r/g, '\r'));
+          out = '';
+        }
+        /* istanbul ignore next */
+        setTimeout(function () {
+          cb();
+        }, 150);
+      });
+
+      proc.on('error', function (data) {
+        out += data.toString('utf8');
+      });
+    });
+  }
+};
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100755
index 0000000..0cf4688
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,127 @@
+'use strict';
+
+const $ = require('shelljs');
+const babel = require('gulp-babel');
+const changed = require('gulp-changed');
+const eslint = require('gulp-eslint');
+const fs = require('fs');
+const gulp = require('gulp');
+
+gulp.task('lint', function () {
+  return gulp.src(['src/*.js', './*.js', './bin/*.js'])
+    .pipe(eslint())
+    .pipe(eslint.format());
+});
+gulp.task('babel', function () {
+  const bab = babel();
+  gulp.src('src/**/*.js')
+    .pipe(changed('dist'))
+    .pipe(bab)
+    .pipe(gulp.dest('dist'));
+  return;
+});
+
+gulp.task('build', function () {
+  const commands = require('./commands.json');
+  for (let i = 0; i < commands.commands.length; ++i) {
+    const command = commands.commands[i];
+    const content = `#!/usr/bin/env node\nrequire('./parser')(process.argv, '${command}');\n`;
+    fs.writeFileSync(`./bin/${command}.js`, content);
+  }
+});
+
+function getJSON(name) {
+  const dir = `./packages/${name}`;
+  let json;
+  try {
+    json = fs.readFileSync(`${dir}/package.json`, {encoding: 'utf8', force: true});
+    json = JSON.parse(json);
+  } catch (e) {
+    $.cp('-f', `./packages/template.package.json`, `${dir}/package.json`);
+    return getJSON(name);
+  }
+  return json;
+}
+
+function writeJSON(name, json) {
+  const dir = `./packages/${name}`;
+  fs.writeFileSync(`${dir}/package.json`, `${JSON.stringify(json, null, '  ')}\n`);
+}
+
+gulp.task('packages', function () {
+  const commands = require('./commands.json');
+
+  let related = '';
+  related += `- [cash](https://github.com/dthree/cash) - Main project\n`;
+  related += `- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands\n`;
+  related += `- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal\n\n`;
+  related += `#### Individual commands\n\n`;
+  for (const name in commands.packages) {
+    if (commands.packages.hasOwnProperty(name)) {
+      related += `- [cash-${name}](https://npmjs.com/package/cash-${name})\n`;
+    }
+  }
+
+  related = related.replace(/\n$/g, '');
+
+  for (const name in commands.packages) {
+    if (commands.packages.hasOwnProperty(name)) {
+      const pkg = commands.packages[name];
+      const deps = pkg.dependencies;
+      const files = pkg.files;
+      const dir = `./packages/${name}`;
+      $.rm('-rf', `${dir}/dist`);
+      $.mkdir('-p', `${dir}/dist/help`);
+      $.mkdir('-p', `${dir}/dist/lib`);
+      $.mkdir('-p', `${dir}/dist/commands`);
+      $.mkdir('-p', `${dir}/dist/util`);
+      $.mkdir('-p', `${dir}/bin`);
+      const json = getJSON(name);
+      const jsonMain = require('./package.json');
+      json.dependencies = {};
+      json.devDependencies = {};
+      const main = `./dist/commands/${name}.js`;
+      const help = `./dist/help/${name}.js`;
+      const bin = `./bin/${name}.js`;
+      $.cp('-f', main, `${dir}/${main}`);
+      $.cp('-f', bin, `${dir}/${bin}`);
+      $.cp('-f', help, `${dir}/${help}`);
+      $.cp('-f', './bin/parser.js', `${dir}/bin/parser.js`);
+      $.cp('-fr', `./packages/template.README.md`, `${dir}/README.md`);
+      let readme = String($.cat(`${dir}/README.md`));
+      readme = readme.replace(/\{package\-name\}/g, `cash-${name}`);
+      readme = readme.replace(/\{command\-name\}/g, `${name}`);
+      readme = readme.replace(/\{related\}/g, related);
+      readme.to(`${dir}/README.md`);
+      for (let i = 0; i < files.length; ++i) {
+        $.cp('-f', files[i], `${dir}/${files[i]}`);
+      }
+      for (let i = 0; i < deps.length; ++i) {
+        json.dependencies[deps[i]] = jsonMain.dependencies[deps[i]];
+        if (json.dependencies[deps[i]] === undefined) {
+          throw new Error(`Sub-module dependency for "${name}" does not exist in the main package.json file.`);
+        }
+      }
+      json.files = ['dist', 'bin'];
+      json.dependencies.vorpal = jsonMain.dependencies.vorpal;
+      json.name = `cash-${name}`;
+      json.description = `Cross-platform implementation of the Unix '${name}' command.`;
+      json.main = main;
+      json.bin = json.bin || {};
+      json.bin[name] = bin;
+      writeJSON(name, json);
+    }
+  }
+  if ($.test('-e', './../cash-global/commands.json')) {
+    $.cp('./commands.json', './../cash-global/commands.json');
+  }
+});
+
+gulp.task('watch', function () {
+  gulp.watch('src/**/*.js', ['babel', 'build', 'packages']);
+  gulp.watch('commands.json', ['babel', 'build', 'packages']);
+  gulp.watch('test/**/*.js', ['babel', 'build', 'packages']);
+});
+
+gulp.task('default', ['babel', 'watch', 'build', 'packages']);
+
diff --git a/package.json b/package.json
new file mode 100755
index 0000000..6c7e6c3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,103 @@
+{
+  "name": "cash",
+  "version": "0.2.1",
+  "description": "Cross-platform Linux commands in pure ES6.",
+  "main": "./lib/index.js",
+  "scripts": {
+    "test": "./node_modules/istanbul/lib/cli.js cover --root './dist' -x './dist/lib/sugar.js' _mocha -- -R spec && npm run lint",
+    "test-win": "mocha",
+    "lint": "xo ./src/*.js ./src/**/*.js ./test/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "shell",
+    "shelljs",
+    "bash",
+    "cash",
+    "$",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {
+    "babel-core": "^6.5.2",
+    "babel-preset-es2015": "^6.5.0",
+    "coveralls": "^2.11.6",
+    "gulp": "^3.9.0",
+    "gulp-babel": "^6.1.2",
+    "gulp-changed": "^1.3.0",
+    "gulp-eslint": "^2.0.0",
+    "istanbul": "^0.4.2",
+    "mocha": "^2.2.5",
+    "shelljs": "^0.6.0",
+    "should": "^7.0.3",
+    "webpack": "^1.12.13",
+    "xo": "^0.12.1"
+  },
+  "bin": {
+    "$": "./bin/cash.js",
+    "cash": "./bin/cash.js"
+  },
+  "dependencies": {
+    "chalk": "^1.1.0",
+    "filesize": "^3.1.3",
+    "fkill": "^3.1.0",
+    "fs-extra": "^0.23.1",
+    "glob": "^6.0.4",
+    "lodash": "^4.0.0",
+    "minimist": "^1.2.0",
+    "username": "^1.0.1",
+    "vorpal": "^1.9.5",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "vorpal-grep": "^0.1.2",
+    "vorpal-less": "0.0.13"
+  },
+  "engines": {
+    "node": ">= 4",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "commands.json",
+    "dist",
+    "bin"
+  ],
+  "xo": {
+    "envs": [
+      "node",
+      "mocha"
+    ],
+    "space": true,
+    "esnext": true,
+    "rules": {
+      "prefer-arrow-callback": 0,
+      "no-loop-func": 0,
+      "no-nested-ternary": 0,
+      "no-constant-condition": 0,
+      "no-use-extend-native/no-use-extend-native": 0,
+      "no-negated-condition": 0,
+      "no-inner-declarations": 0,
+      "prefer-reflect": 0,
+      "wrap-iife": 0,
+      "no-unused-expressions": 0,
+      "global-require": 0
+    }
+  }
+}
diff --git a/packages/cat/README.md b/packages/cat/README.md
new file mode 100755
index 0000000..a56c8e4
--- /dev/null
+++ b/packages/cat/README.md
@@ -0,0 +1,47 @@
+# cash-cat
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `cat` command.
+
+```bash
+npm install cash-cat -g
+```
+
+This will install `cat` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> cat --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/cat/bin/cat.js b/packages/cat/bin/cat.js
new file mode 100644
index 0000000..c82524a
--- /dev/null
+++ b/packages/cat/bin/cat.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cat');
diff --git a/packages/cat/bin/parser.js b/packages/cat/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/cat/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/cat/dist/commands/cat.js b/packages/cat/dist/commands/cat.js
new file mode 100755
index 0000000..ee21984
--- /dev/null
+++ b/packages/cat/dist/commands/cat.js
@@ -0,0 +1,116 @@
+'use strict';
+
+var _ = require('lodash');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var lpad = require('./../util/lpad');
+var strip = require('./../util/stripAnsi');
+
+var cat = {
+  exec: function exec(args, options) {
+    var self = this;
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    // -A handler
+    if (options.showall) {
+      options.shownonprinting = true;
+      options.showends = true;
+      options.showtabs = true;
+    }
+
+    // -e handler
+    if (options.e) {
+      options.shownonprinting = true;
+      options.showends = true;
+    }
+
+    // -t handler
+    if (options.t) {
+      options.shownonprinting = true;
+      options.showtabs = true;
+    }
+
+    var stdout = '';
+    try {
+      var stdin = fetch(args.files, args.stdin, {
+        onDirectory: function onDirectory(name) {
+          return 'cat: ' + name + ': Is a directory';
+        },
+        onInvalidFile: function onInvalidFile(name) {
+          return 'cat: ' + name + ': No such file or directory';
+        }
+      });
+      var ctr = 0;
+      for (var i = 0; i < stdin.length; ++i) {
+        // If -s, squeeze double blank lines to a
+        // single line.
+        if (options.squeezeblank) {
+          stdin[i] = stdin[i].replace(/\n\n\s*\n/g, '\n\n');
+        }
+        if (options.showtabs) {
+          stdin[i] = stdin[i].replace(/\t/g, '^I');
+        }
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        stdin[i] = stdin[i].replace(/\s$/, '');
+        var parts = String(stdin[i]).split('\n');
+        for (var j = 0; j < parts.length; ++j) {
+          var blank = strip(parts[j]).trim() === '';
+          // If -b, number every non-blank line
+          // If -n, number every line
+          var numbered = !blank && options.numbernonblank || options.number && !options.numbernonblank;
+          if (numbered) {
+            ctr++;
+          }
+          var numStr = numbered ? lpad(String(ctr), 6, ' ') + '  ' : '';
+          // If -E, append a $ to each line end.
+          var dollarStr = options.showends ? '$' : '';
+          var line = numStr + parts[j] + dollarStr;
+          self.log(line);
+          stdout += line + '\n';
+        }
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return 1;
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cat;
+  }
+  vorpal.api.cat = cat;
+  vorpal.command('cat [files...]').option('-A, --show-all', 'equivalent to -vET').option('-b, --number-nonblank', 'number nonempty output lines, overrides -n').option('-e', 'equivalent to -vE').option('-E, --show-ends', 'display $ at end of each line').option('-n, --number', 'number all output lines').option('-s, --squeeze-blank', 'suppress repeated empty output lines').option('-t', 'equivalent to -vT').option('-T, --show-tabs', 'display TAB characters as ^I').option('-v, --show-nonprinting', 'use ^ and M- notation, except for LFD and TAB') // this doesn't work yet...
+  .autocomplete(fsAutocomplete()).action(function (args, cb) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: cat,
+      args: args,
+      options: args.options,
+      callback: cb
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/cat/dist/help/cat.js b/packages/cat/dist/help/cat.js
new file mode 100755
index 0000000..42872c7
--- /dev/null
+++ b/packages/cat/dist/help/cat.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cat [OPTION]... [FILE]...\nConcatenate FILE(s), or standard input, to standard output.\n\n  -A, --show-all           equivalent to -vET\n  -b, --number-nonblank    number nonempty output lines, overrides -n\n  -e                       equivalent to -vE\n  -E, --show-ends          display $ at end of each line\n  -n, --number             number all output lines\n  -s, --squeeze-blank      suppress repeated empty output lines\n  -t                       equivalent to -vT\n  -T, --show-tabs          display TAB characters as ^I\n  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB\n      --help               display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nExamples:\n  cat f - g  Output f's contents, then standard input, then g's contents.\n  cat        Copy standard input to standard output.\n\nReport cat bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/cat/dist/util/expand.js b/packages/cat/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/packages/cat/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/packages/cat/dist/util/fetch.js b/packages/cat/dist/util/fetch.js
new file mode 100755
index 0000000..da862df
--- /dev/null
+++ b/packages/cat/dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+  files = files || [];
+  stdin = stdin !== undefined ? stdin : [];
+  var f = expand(files);
+
+  if (!(f.length === 0 && files.length > 0)) {
+    files = f;
+  }
+
+  for (var i = 0; i < files.length; ++i) {
+    try {
+      var stat = fs.statSync(files[i]);
+      if (stat.isDirectory()) {
+        files[i] = options.onDirectory(files[i]);
+      } else {
+        files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+      }
+    } catch (e) {
+      files[i] = options.onInvalidFile(files[i]);
+    }
+  }
+
+  var agg = files.length < 1 ? stdin : files;
+  var final = [];
+
+  for (var i = 0; i < agg.length; ++i) {
+    if (agg[i] !== undefined) {
+      final.push(agg[i]);
+    }
+  }
+  return final;
+};
\ No newline at end of file
diff --git a/packages/cat/dist/util/interfacer.js b/packages/cat/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/cat/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/cat/dist/util/lpad.js b/packages/cat/dist/util/lpad.js
new file mode 100755
index 0000000..61d8da7
--- /dev/null
+++ b/packages/cat/dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  var len = Math.max(0, width - strip(str).length);
+  return Array(len + 1).join(delimiter) + str;
+};
\ No newline at end of file
diff --git a/packages/cat/dist/util/stripAnsi.js b/packages/cat/dist/util/stripAnsi.js
new file mode 100755
index 0000000..e05149e
--- /dev/null
+++ b/packages/cat/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+  var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+  return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
\ No newline at end of file
diff --git a/packages/cat/package.json b/packages/cat/package.json
new file mode 100644
index 0000000..29cb0b1
--- /dev/null
+++ b/packages/cat/package.json
@@ -0,0 +1,51 @@
+{
+  "name": "cash-cat",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'cat' command.",
+  "main": "./dist/commands/cat.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "cat": "./bin/cat.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "glob": "^6.0.4",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/cp/README.md b/packages/cp/README.md
new file mode 100755
index 0000000..2a0e144
--- /dev/null
+++ b/packages/cp/README.md
@@ -0,0 +1,47 @@
+# cash-cp
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `cp` command.
+
+```bash
+npm install cash-cp -g
+```
+
+This will install `cp` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> cp --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/cp/bin/cp.js b/packages/cp/bin/cp.js
new file mode 100644
index 0000000..a14fb86
--- /dev/null
+++ b/packages/cp/bin/cp.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cp');
diff --git a/packages/cp/bin/parser.js b/packages/cp/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/cp/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/cp/dist/commands/cp.js b/packages/cp/dist/commands/cp.js
new file mode 100755
index 0000000..cce41f0
--- /dev/null
+++ b/packages/cp/dist/commands/cp.js
@@ -0,0 +1,207 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+var os = require('os');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var cp = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+
+    args = args === undefined ? [] : args;
+    args = _.isArray(args) ? args : args.split(' ');
+    args = _.filter(args, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    options.noclobber = options.force === true ? false : options.noclobber;
+    options.recursive = options.R === true ? true : options.recursive;
+
+    if (args.length < 1) {
+      this.log('cp: missing file operand\nTry \'cp --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log('cp: missing destination file operand after ' + args[0] + '\nTry \'cp --help\' for more information.');
+      return 1;
+    }
+
+    args = expand(args);
+
+    var dest = args.pop();
+    var sources = args;
+
+    var exists = fs.existsSync(dest);
+    var stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log('cp: target ' + dest + ' is not a directory');
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.recursive) {
+      sources.forEach(function (src, i) {
+        if (src[src.length - 1] === '/') {
+          sources[i] += '*';
+        } else if (fs.statSync(src).isDirectory() && !exists) {
+          sources[i] += '/*';
+        }
+      });
+      try {
+        fs.mkdirSync(dest, parseInt('0777', 8));
+      } catch (e) {
+        // like Unix's cp, keep going even if we can't create dest dir
+      }
+    }
+
+    sources = expand(sources);
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log('cp: cannot stat ' + src + ': No such file or directory');
+        return;
+      }
+
+      if (fs.statSync(src).isDirectory()) {
+        if (!options.recursive) {
+          self.log('cp: omitting directory ' + src);
+        } else {
+          // 'cp /a/source dest' should create 'source' in 'dest'
+          var newDest = path.join(dest, path.basename(src));
+          var checkDir = fs.statSync(src);
+          try {
+            fs.mkdirSync(newDest, checkDir.mode);
+          } catch (e) {
+            /* istanbul ignore if */
+            if (e.code !== 'EEXIST') {
+              throw new Error();
+            }
+          }
+          cpdirSyncRecursive.call(self, src, newDest, options);
+        }
+        return;
+      }
+
+      // If here, src is a file
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      var iDest = dest;
+      if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
+        iDest = path.normalize(dest + '/' + path.basename(src));
+      }
+
+      if (fs.existsSync(iDest) && options.no_force) {
+        return;
+      }
+
+      copyFileSync.call(self, src, iDest);
+    });
+  }
+};
+
+function cpdirSyncRecursive(sourceDir, destDir, options) {
+  var self = this;
+  /* istanbul ignore if */
+  if (!options) {
+    options = {};
+  }
+  var checkDir = fs.statSync(sourceDir);
+  try {
+    fs.mkdirSync(destDir, checkDir.mode);
+  } catch (e) {
+    /* istanbul ignore if */
+    if (e.code !== 'EEXIST') {
+      throw e;
+    }
+  }
+  var files = fs.readdirSync(sourceDir);
+  for (var i = 0; i < files.length; i++) {
+    var srcFile = sourceDir + '/' + files[i];
+    var destFile = destDir + '/' + files[i];
+    var srcFileStat = fs.lstatSync(srcFile);
+    if (srcFileStat.isDirectory()) {
+      // recursion this thing right on back.
+      cpdirSyncRecursive.call(self, srcFile, destFile, options);
+    } else if (srcFileStat.isSymbolicLink()) {
+      var symlinkFull = fs.readlinkSync(srcFile);
+      fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null);
+      // At this point, we've hit a file actually worth copying... so copy it on over.
+    } else if (fs.existsSync(destFile) && options.noclobber) {
+        // be silent
+      } else {
+          copyFileSync.call(self, srcFile, destFile);
+        }
+  }
+}
+
+function copyFileSync(src, dest) {
+  /* istanbul ignore if */
+  if (!fs.existsSync(src)) {
+    this.log('cp: cannot stat ' + src + ': No such file or directory');
+    return;
+  }
+
+  var BUF_LENGTH = 64 * 1024;
+  var buf = new Buffer(BUF_LENGTH);
+  var bytesRead = BUF_LENGTH;
+  var pos = 0;
+  var fdr = null;
+  var fdw = null;
+
+  try {
+    fdr = fs.openSync(src, 'r');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log('cp: cannot open ' + src + ': ' + e.code);
+    /* istanbul ignore next */
+    return;
+  }
+
+  try {
+    fdw = fs.openSync(dest, 'w');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log('cp: cannot write to destination file ' + dest + ': ' + e.code);
+    /* istanbul ignore next */
+    return;
+  }
+
+  while (bytesRead === BUF_LENGTH) {
+    bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+    fs.writeSync(fdw, buf, 0, bytesRead);
+    pos += bytesRead;
+  }
+
+  fs.closeSync(fdr);
+  fs.closeSync(fdw);
+  fs.chmodSync(dest, fs.statSync(src).mode);
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cp;
+  }
+  vorpal.api.cp = cp;
+  vorpal.command('cp [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('-r, --recursive', 'copy directories recursively').option('-R', 'copy directories recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: cp,
+      args: args.args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/cp/dist/help/cp.js b/packages/cp/dist/help/cp.js
new file mode 100755
index 0000000..52be2d7
--- /dev/null
+++ b/packages/cp/dist/help/cp.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cp [OPTION]... [-T] SOURCE DEST\n  or:  cp [OPTION]... SOURCE... DIRECTORY\nCopy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\n  -f, --force           if an existing destination file cannot be\n                          opened, remove it and try again (this option\n                          is ignored when the -n option is also used)\n  -n, --no-clobber      do not overwrite an existing file (overrides\n                          a previous -i option)\n  -R, -r, --recursive   copy directories recursively\n      --help            display this help and exit\n\nReport cp bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/cp/dist/util/expand.js b/packages/cp/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/packages/cp/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/packages/cp/dist/util/interfacer.js b/packages/cp/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/cp/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/cp/package.json b/packages/cp/package.json
new file mode 100644
index 0000000..b55b7e1
--- /dev/null
+++ b/packages/cp/package.json
@@ -0,0 +1,51 @@
+{
+  "name": "cash-cp",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'cp' command.",
+  "main": "./dist/commands/cp.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "cp": "./bin/cp.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "glob": "^6.0.4",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/kill/README.md b/packages/kill/README.md
new file mode 100755
index 0000000..6991579
--- /dev/null
+++ b/packages/kill/README.md
@@ -0,0 +1,47 @@
+# cash-kill
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `kill` command.
+
+```bash
+npm install cash-kill -g
+```
+
+This will install `kill` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> kill --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/kill/bin/kill.js b/packages/kill/bin/kill.js
new file mode 100644
index 0000000..06959b5
--- /dev/null
+++ b/packages/kill/bin/kill.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'kill');
diff --git a/packages/kill/bin/parser.js b/packages/kill/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/kill/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/kill/dist/commands/kill.js b/packages/kill/dist/commands/kill.js
new file mode 100755
index 0000000..226ded1
--- /dev/null
+++ b/packages/kill/dist/commands/kill.js
@@ -0,0 +1,97 @@
+'use strict';
+
+var _ = require('lodash');
+var fkill = require('fkill');
+var os = require('os');
+
+var interfacer = require('./../util/interfacer');
+
+var usage = 'kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]';
+var windows = os.platform().indexOf('win') > -1;
+var signals = {
+  SIGKILL: 9,
+  SIGTERM: 15,
+  KILL: 9,
+  TERM: 15,
+  9: 'KILL',
+  15: 'TERM'
+};
+
+var kill = {
+  exec: function exec(args, options) {
+    options = options || {};
+
+    var procs = args;
+    procs = procs === undefined ? [] : procs;
+    procs = typeof procs === 'string' ? String(procs).split(' ') : procs;
+    procs = _.filter(procs, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    function log(str) {
+      if (options.vorpal) {
+        options.vorpal.log(str);
+      } else {
+        /* istanbul ignore next */
+        console.log(str);
+      }
+    }
+
+    if (options.l !== undefined) {
+      if (options.l === true) {
+        this.log(' 9) SIGKILL   15) SIGTERM');
+        return 0;
+      }
+      if (signals[options.l]) {
+        this.log(signals[options.l]);
+        return 0;
+      }
+      this.log('-cash: kill: ' + options.l + ': invalid signal specification');
+      return 0;
+    }
+
+    if (procs.length < 1) {
+      this.log(usage);
+      return 0;
+    }
+
+    var forced = options['9'] === true || options.n === 9 || String(options.s).toLowerCase() === 'sigkill' || String(options.s).toLowerCase() === 'kill';
+    var opts = { force: forced };
+
+    var _loop = function _loop(i) {
+      var proc = procs[i];
+      proc = !isNaN(proc) ? parseFloat(proc) : proc;
+      proc = windows && isNaN(proc) && proc.indexOf('.') === -1 ? proc + '.exe' : proc;
+      fkill(proc, opts).then(function () {
+        // .. chill
+      }).catch(function (err) {
+        if (String(err.message).indexOf('failed') > -1) {
+          log('-cash: kill: (' + proc + ') - No such process');
+        }
+      });
+    };
+
+    for (var i = 0; i < procs.length; ++i) {
+      _loop(i);
+    }
+
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return kill;
+  }
+  vorpal.api.kill = kill;
+  vorpal.command('kill [process...]').option('-9', 'sigkill').option('-s [sig]', 'sig is a signal name').option('-n [sig]', 'sig is a signal number').option('-l [sigspec]', 'list the signal names').action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: kill,
+      args: args.process,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/kill/dist/help/kill.js b/packages/kill/dist/help/kill.js
new file mode 100755
index 0000000..ce76bf9
--- /dev/null
+++ b/packages/kill/dist/help/kill.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: kill [OPTION] pid | jobspec ... or kill -l [sigspec]\nSend a signal to a job.\n\nSend the processes identified by PID or JOBSPEC the signal named by\nSIGSPEC or SIGNUM.  If neither SIGSPEC nor SIGNUM is present, then\nSIGTERM is assumed.\n\n  -s sig         SIG is a signal name\n  -n sig         SIG is a signal number\n  -l [sigspec]   list the signal names; if arguments follow `-l' they\n                 are assumed to be signal numbers for which names\n                 should be listed\n      --help     display this help and exit\n\nExit status:\n  0   if OK,\n  1   if an invalid option is given or an error occurs.\n\nReport kill bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/kill/dist/util/interfacer.js b/packages/kill/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/kill/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/kill/package.json b/packages/kill/package.json
new file mode 100644
index 0000000..3e1f13f
--- /dev/null
+++ b/packages/kill/package.json
@@ -0,0 +1,50 @@
+{
+  "name": "cash-kill",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'kill' command.",
+  "main": "./dist/commands/kill.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "kill": "./bin/kill.js"
+  },
+  "dependencies": {
+    "fkill": "^3.1.0",
+    "lodash": "^4.0.0",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/ls/README.md b/packages/ls/README.md
new file mode 100755
index 0000000..81c25d6
--- /dev/null
+++ b/packages/ls/README.md
@@ -0,0 +1,47 @@
+# cash-ls
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `ls` command.
+
+```bash
+npm install cash-ls -g
+```
+
+This will install `ls` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> ls --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/ls/bin/ls.js b/packages/ls/bin/ls.js
new file mode 100644
index 0000000..ae0712e
--- /dev/null
+++ b/packages/ls/bin/ls.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'ls');
diff --git a/packages/ls/bin/parser.js b/packages/ls/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/ls/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/ls/dist/commands/ls.js b/packages/ls/dist/commands/ls.js
new file mode 100755
index 0000000..0055439
--- /dev/null
+++ b/packages/ls/dist/commands/ls.js
@@ -0,0 +1,353 @@
+'use strict';
+
+var _ = require('lodash');
+var chalk = require('chalk');
+var filesize = require('filesize');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var os = require('os');
+
+var colorFile = require('./../util/colorFile');
+var columnify = require('./../util/columnify');
+var dateConverter = require('./../util/converter.date');
+var fileFromPath = require('./../util/fileFromPath');
+var interfacer = require('./../util/interfacer');
+var pad = require('./../util/pad');
+var lpad = require('./../util/lpad');
+var permissionsConverter = require('./../util/converter.permissions');
+var strip = require('./../util/stripAnsi');
+var walkDir = require('./../util/walkDir');
+var walkDirRecursive = require('./../util/walkDirRecursive');
+
+var pads = { pad: pad, lpad: lpad };
+
+var ls = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec: function exec(paths, options) {
+    var self = this;
+    paths = !_.isArray(paths) && _.isObject(paths) ? paths.paths : paths;
+    paths = paths || ['.'];
+    paths = _.isArray(paths) ? paths : [paths];
+    options = options || {};
+    try {
+      var results = [];
+      for (var i = 0; i < paths.length; ++i) {
+        if (options.recursive) {
+          var result = ls.execDirRecursive(paths[i], options);
+          results = results.concat(result);
+        } else {
+          var result = ls.execDir(paths[i], options);
+          results.push(result);
+        }
+      }
+      var stdout = ls.formatAll(results, options);
+      if (strip(stdout).trim() !== '') {
+        self.log(String(stdout).replace(/\\/g, '/'));
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      return ls.error.call(self, e);
+    }
+  },
+
+
+  /**
+   * Returns ls stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error: function error(e) {
+    /* istanbul ignore next */
+    var status = undefined;
+    /* istanbul ignore next */
+    var stdout = undefined;
+    /* istanbul ignore next */
+    if (e.code === 'ENOENT' && e.syscall === 'scandir') {
+      status = 1;
+      stdout = 'ls: cannot access: No such file or directory';
+    } else {
+      /* istanbul ignore next */
+      status = 2;
+      /* istanbul ignore next */
+      stdout = e.stack;
+    }
+    /* istanbul ignore next */
+    this.log(stdout);
+    /* istanbul ignore next */
+    return status;
+  },
+
+
+  /**
+   * Recursively executes `execDir`.
+   * For use with `ls -R`.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDirRecursive: function execDirRecursive(path, options) {
+    var self = this;
+    var results = [];
+    walkDirRecursive(path, function (pth) {
+      var result = self.execDir(pth, options);
+      results.push(result);
+    });
+    return results;
+  },
+
+
+  /**
+   * Executes `ls` functionality
+   * for a given directory.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDir: function execDir(path, options) {
+    var files = [];
+    var rawFiles = [];
+    var totalSize = 0;
+
+    function pushFile(file, data) {
+      rawFiles.push({
+        file: file,
+        data: data
+      });
+    }
+
+    // Add in implied current and parent dirs.
+    pushFile('.', fs.statSync('.'));
+    pushFile('..', fs.statSync('..'));
+
+    // Walk the passed in directory,
+    // pushing the results into `rawFiles`.
+    walkDir(path, pushFile);
+
+    // Sort alphabetically be default,
+    // unless -U is specified, in which case
+    // we don't sort.
+    if (!options.U) {
+      rawFiles = rawFiles.sort(function (a, b) {
+        // Sort by size.
+        if (options.S) {
+          // Hack for windows - a directory lising
+          // in linux says the size is 4096, and Windows
+          // it's 0, leading to inconsistent sorts based
+          // on size, and failing tests.
+          var win = os.platform() === 'win32';
+          a.data.size = win && a.data.isDirectory() && a.data.size === 0 ? 4096 : a.data.size;
+          b.data.size = win && b.data.isDirectory() && b.data.size === 0 ? 4096 : b.data.size;
+          return a.data.size > b.data.size ? -1 : a.data.size < b.data.size ? 1 : 0;
+        }
+        if (options.t) {
+          // Sort by date modified.
+          return a.data.mtime < b.data.mtime ? 1 : b.data.mtime < a.data.mtime ? -1 : 0;
+        }
+        // Sort alphabetically - default.
+        var aFileName = fileFromPath(a.file).trim().toLowerCase().replace(/\W/g, '');
+        var bFileName = fileFromPath(b.file).trim().toLowerCase().replace(/\W/g, '');
+        return aFileName > bFileName ? 1 : aFileName < bFileName ? -1 : 0;
+      });
+    }
+
+    // Reverse whatever sort the user specified.
+    if (options.reverse) {
+      rawFiles.reverse();
+    }
+
+    var _loop = function _loop(i) {
+      var file = rawFiles[i].file;
+      var data = rawFiles[i].data;
+      var fileShort = fileFromPath(file);
+      var dotted = fileShort && fileShort.charAt(0) === '.';
+      var implied = fileShort === '..' || fileShort === '.';
+      var type = data.isDirectory() ? 'd' : '-';
+      var permissions = permissionsConverter.modeToRWX(data.mode);
+      var hardLinks = data.nlink;
+      var size = options.humanreadable ? filesize(data.size, { unix: true }) : data.size;
+      var modified = dateConverter.unix(data.mtime);
+      var owner = data.uid;
+      var group = data.gid;
+      var inode = data.ino;
+
+      totalSize += data.size;
+
+      var fileName = fileShort;
+
+      // If --classify, add '/' to end of folders.
+      fileName = options.classify && data.isDirectory() ? fileName + '/' : fileName;
+
+      // If getting --directory, give full path.
+      fileName = options.directory && file === '.' ? path : fileName;
+
+      // Color the files based on $LS_COLORS
+      fileName = data.isFile() ? colorFile(fileName) : fileName;
+
+      // If not already colored and is executable,
+      // make it green
+      var colored = strip(fileName) !== fileName;
+      if (String(permissions).indexOf('x') > -1 && !colored && data.isFile()) {
+        fileName = chalk.green(fileName);
+      }
+
+      // If --quote-name, wrap in double quotes;
+      fileName = options.quotename ? '"' + fileName + '"' : fileName;
+
+      // Make directories cyan.
+      fileName = data.isDirectory() ? chalk.cyan(fileName) : fileName;
+
+      var include = function () {
+        var directory = options.directory;
+        var all = options.all;
+        var almostAll = options.almostall;
+        var result = false;
+        if (directory && file !== '.') {
+          result = false;
+        } else if (!dotted) {
+          result = true;
+        } else if (all) {
+          result = true;
+        } else if (!implied && almostAll) {
+          result = true;
+        } else if (directory && file === '.') {
+          result = true;
+        }
+        return result;
+      }();
+
+      var details = [type + permissions, hardLinks, owner, group, size, modified, fileName];
+
+      if (options.inode) {
+        details.unshift(inode);
+      }
+
+      var result = options.l && !options.x ? details : fileName;
+
+      if (include) {
+        files.push(result);
+      }
+    };
+
+    for (var i = 0; i < rawFiles.length; ++i) {
+      _loop(i);
+    }
+
+    var result = undefined;
+
+    // If we have the detail view, draw out
+    // all of the details of each file.
+    // Otherwise, just throw the file names
+    // into columns.
+    if (_.isArray(files[0])) {
+      var longest = {};
+      for (var i = 0; i < files.length; ++i) {
+        for (var j = 0; j < files[i].length; ++j) {
+          var len = String(files[i][j]).length;
+          longest[j] = longest[j] || 0;
+          longest[j] = len > longest[j] ? len : longest[j];
+        }
+      }
+
+      var newFiles = [];
+      for (var i = 0; i < files.length; ++i) {
+        var glob = '';
+        for (var j = 0; j < files[i].length; ++j) {
+          var padFn = j === files[i].length - 1 ? 'pad' : 'lpad';
+          if (j === files[i].length - 1) {
+            glob += String(files[i][j]);
+          } else {
+            glob += pads[padFn](String(files[i][j]), longest[j], ' ') + ' ';
+          }
+        }
+        newFiles.push(String(glob));
+      }
+      result = newFiles.join('\n');
+    } else if (options['1']) {
+      result = files.join('\n');
+    } else {
+      var opt = {};
+      if (options.width) {
+        opt.width = options.width;
+      }
+      result = columnify(files, opt);
+    }
+
+    return {
+      path: path,
+      size: options.humanreadable ? filesize(totalSize, { unix: true }) : totalSize,
+      results: result
+    };
+  },
+
+
+  /**
+   * Concatenates the results of multiple
+   * `execDir` functions into their proper
+   * form based on options provided.
+   *
+   * @param {String} results
+   * @param {Object} options
+   * @return {String} stdout
+   * @api private
+   */
+
+  formatAll: function formatAll(results, options) {
+    var stdout = '';
+    if (results.length > 1) {
+      for (var i = 0; i < results.length; ++i) {
+        stdout += results[i].path + ':\n';
+        if (options.l) {
+          stdout += 'total ' + results[i].size + '\n';
+        }
+        stdout += results[i].results;
+        if (i !== results.length - 1) {
+          stdout += '\n\n';
+        }
+      }
+    } else if (results.length === 1) {
+      if (options.l && !options.x) {
+        stdout += 'total ' + results[0].size + '\n';
+      }
+      stdout += results[0].results;
+    }
+    return stdout;
+  }
+};
+
+/**
+ * Expose as a Vorpal extension.
+ */
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return ls;
+  }
+  vorpal.api.ls = ls;
+  vorpal.command('ls [paths...]').option('-a, --all', 'do not ignore entries starting with .').option('-A, --almost-all', 'do not list implied . and ..').option('-d, --directory', 'list directory entries instead of contents, and do not dereference symbolic links').option('-F, --classify', 'append indicator (one of */=>@|) to entries').option('-h, --human-readable', 'with -l, print sizes in human readable format (e.g., 1K 234M 2G)').option('-i, --inode', 'print the index number of each file').option('-l', 'use a long listing format').option('-Q, --quote-name', 'enclose entry names in double quotes').option('-r, --reverse', 'reverse order while sorting').option('-R, --recursive', 'list subdirectories recursively').option('-S', 'sort by file size').option('-t', 'sort by modification time, newest first').option('-U', 'do not sort; list entries in directory order').option('-w, --width [COLS]', 'assume screen width instead of current value').option('-x', 'list entries by lines instead of columns').option('-1', 'list one file per line').autocomplete(fsAutocomplete()).action(function (args, cb) {
+    return interfacer.call(this, {
+      command: ls,
+      args: args.paths,
+      options: args.options,
+      callback: cb
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/ls/dist/help/ls.js b/packages/ls/dist/help/ls.js
new file mode 100755
index 0000000..7c154a0
--- /dev/null
+++ b/packages/ls/dist/help/ls.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs (the current directory by default).\nSort entries alphabetically if none of -tSU nor --sort is specified.\n\n  -a, --all                  do not ignore entries starting with .\n  -A, --almost-all           do not list implied . and ..\n  -d, --directory            list directory entries instead of contents,\n                               and do not dereference symbolic links\n  -f                         do not sort, enable -aU, disable -ls --color\n  -F, --classify             append indicator (one of */=>@|) to entries\n  -h, --human-readable       with -l, print sizes in human readable format\n  -i, --inode                print the index number of each file\n  -l                         use a long listing format\n  -q, --hide-control-chars   print ? instead of non graphic characters\n  -r, --reverse              reverse order while sorting\n  -R, --recursive            list subdirectories recursively\n  -S                         sort by file size\n  -t                         sort by modification time, newest first\n  -U                         do not sort; list entries in directory order\n  -w, --width=COLS           assume screen width instead of current value\n  -x                         list entries by lines instead of by columns\n  -1                         list one file per line\n      --help                 display this help and exit\n\nExit status:\n  0   if OK,\n  1   if minor problems (e.g., cannot access subdirectory),\n  2   if serious trouble (e.g., cannot access command-line argument).\n\nReport ls bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/ls/dist/util/colorFile.js b/packages/ls/dist/util/colorFile.js
new file mode 100755
index 0000000..2368f96
--- /dev/null
+++ b/packages/ls/dist/util/colorFile.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+var chalk = {};
+var map = { cyan: 36, red: 31, magenta: 35 };
+Object.keys(map).forEach(function (key, value) {
+  chalk[key] = function (str) {
+    return '\u001b[' + value + 'm' + str + '\u001b[39m';
+  };
+});
+
+/**
+ * Wraps file strings in ANSI colors
+ * based on their extension.
+ *
+ * @param {file} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (file) {
+  var audio = ['aac', 'au', 'flac', 'mid', 'midi', 'mka', 'mp3', 'mpc', 'ogg', 'ra', 'wav', 'axa', 'oga', 'spx', 'xspf'];
+  var archive = ['tar', 'tgz', 'arj', 'taz', 'lzh', 'lzma', 'tlz', 'txz', 'zip', 'z', 'Z', 'dz', 'gz', 'lz', 'xz', 'bz2', 'bz', 'tbz', 'tbz2', 'tz', 'deb', 'rpm', 'jar', 'rar', 'ace', 'zoo', 'cpio', '7z', 'rz'];
+  var images = ['jpg', 'jpeg', 'gif', 'bmp', 'pbm', 'pgm', 'ppm', 'tga', 'xbm', 'xpm', 'tif', 'tiff', 'png', 'svg', 'svgz', 'mng', 'pcx', 'mov', 'mpg', 'mpeg', 'm2v', 'mkv', 'ogm', 'mp4', 'm4v', 'mp4v', 'vob', 'qt', 'nuv', 'wmv', 'asf', 'rm', 'rmvb', 'flc', 'avi', 'fli', 'flv', 'gl', 'dl', 'xcf', 'xwd', 'yuv', 'cgm', 'emf', 'axv', 'anx', 'ogv', 'ogx'];
+
+  var extension = String(file).toLowerCase().trim().split('.');
+  extension = extension[extension.length - 1];
+
+  var colored = strip(file);
+  colored = audio.indexOf(extension) > -1 ? chalk.cyan(file) : archive.indexOf(extension) > -1 ? chalk.red(file) : images.indexOf(extension) > -1 ? chalk.magenta(file) : colored;
+
+  return colored;
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/columnify.js b/packages/ls/dist/util/columnify.js
new file mode 100755
index 0000000..6f5a46e
--- /dev/null
+++ b/packages/ls/dist/util/columnify.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+var pad = require('./pad');
+
+/**
+ * Formats an array to display in a TTY
+ * in a pretty fashion.
+ *
+ * @param {Array} arr
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (arr, options) {
+  arr = arr || [];
+  options = options || {};
+  var bk = JSON.parse(JSON.stringify(arr));
+  var width = options.width && !isNaN(options.width) ? options.width : process.stdout.columns;
+  var longest = strip(bk.sort(function (a, b) {
+    return strip(b).length - strip(a).length;
+  })[0] || '').length + 2;
+  var fullWidth = strip(arr.join('')).length;
+  var fitsOneLine = fullWidth + arr.length * 2 <= width;
+  var cols = Math.floor(width / longest);
+  cols = cols < 1 ? 1 : cols;
+  if (fitsOneLine) {
+    return arr.join('  ');
+  }
+  var col = 0;
+  var lines = [];
+  var line = '';
+  for (var i = 0; i < arr.length; ++i) {
+    if (col < cols) {
+      col++;
+    } else {
+      if (String(strip(line)).trim() !== '') {
+        lines.push(line);
+      }
+      line = '';
+      col = 1;
+    }
+    if (cols === 1) {
+      // If we have files so damn
+      // long that we wrap, don't pad
+      // the lines.
+      line += arr[i];
+    } else {
+      // Pad the lines based on the
+      // longest word.
+      line += pad(arr[i], longest, ' ');
+    }
+  }
+  if (line !== '') {
+    lines.push(line);
+  }
+  return lines.join('\n');
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/converter.date.js b/packages/ls/dist/util/converter.date.js
new file mode 100755
index 0000000..17b2b52
--- /dev/null
+++ b/packages/ls/dist/util/converter.date.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * Date conversion utilities
+ */
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(num, padding) {
+  padding = padding || '0';
+  num = parseFloat(num);
+  if (num < 10) {
+    return '' + padding + num;
+  }
+  return num;
+}
+
+module.exports = {
+  unix: function unix(dt) {
+    var date = dt;
+    var day = pad(date.getDate(), ' ');
+    var month = months[date.getMonth()];
+    var hour = pad(date.getHours());
+    var min = pad(date.getMinutes());
+    var hourMin = hour + ':' + min;
+    day = day.length === 1 ? ' ' + day : day;
+    date = month + ' ' + day + ' ' + hourMin;
+    return date;
+  }
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/converter.permissions.js b/packages/ls/dist/util/converter.permissions.js
new file mode 100755
index 0000000..6cbe2f2
--- /dev/null
+++ b/packages/ls/dist/util/converter.permissions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+/**
+ * Permission conversion utilities
+ */
+
+module.exports = {
+
+  listing: {
+    0: '---',
+    1: '--x',
+    2: '-w-',
+    3: '-wx',
+    4: 'r--',
+    5: 'r-x',
+    6: 'rw-',
+    7: 'rwx'
+  },
+
+  modeToRWX: function modeToRWX(mode) {
+    var octal = this.modeToOctal(mode);
+    var rwx = this.octalToRWX(octal);
+    return rwx;
+  },
+  modeToOctal: function modeToOctal(mode) {
+    var octal = '0' + (mode & 511).toString(8);
+    return octal;
+  },
+  octalToRWX: function octalToRWX(octal) {
+    if (!octal) {
+      return undefined;
+    }
+    var list = this.listing;
+    var a = list[String(octal).charAt(1)];
+    var b = list[String(octal).charAt(2)];
+    var c = list[String(octal).charAt(3)];
+    return a + b + c;
+  }
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/fileFromPath.js b/packages/ls/dist/util/fileFromPath.js
new file mode 100755
index 0000000..0583f23
--- /dev/null
+++ b/packages/ls/dist/util/fileFromPath.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * Parses a path and returns just the file
+ *
+ * @param {path} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (path) {
+  var fileShort = String(path).split('/');
+  fileShort = fileShort[fileShort.length - 1];
+  fileShort = fileShort.split('\\');
+  fileShort = fileShort[fileShort.length - 1];
+  return fileShort;
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/interfacer.js b/packages/ls/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/ls/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/lpad.js b/packages/ls/dist/util/lpad.js
new file mode 100755
index 0000000..61d8da7
--- /dev/null
+++ b/packages/ls/dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  var len = Math.max(0, width - strip(str).length);
+  return Array(len + 1).join(delimiter) + str;
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/pad.js b/packages/ls/dist/util/pad.js
new file mode 100755
index 0000000..b6eaeb7
--- /dev/null
+++ b/packages/ls/dist/util/pad.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads a value with with space or
+ * a specified delimiter to match a
+ * given width.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  var len = Math.max(0, width - strip(str).length);
+  return str + Array(len + 1).join(delimiter);
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/stripAnsi.js b/packages/ls/dist/util/stripAnsi.js
new file mode 100755
index 0000000..e05149e
--- /dev/null
+++ b/packages/ls/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+  var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+  return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/walkDir.js b/packages/ls/dist/util/walkDir.js
new file mode 100755
index 0000000..bfeabc2
--- /dev/null
+++ b/packages/ls/dist/util/walkDir.js
@@ -0,0 +1,41 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Walks a single directory calling
+ * a callback function for each file or
+ * folder, returning the path and results
+ * of fs.statSync.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  function readFile(path, cbk) {
+    var stat = undefined;
+    try {
+      stat = fs.statSync(path);
+      if (stat.isFile() || stat.isDirectory()) {
+        cbk(path, stat);
+      }
+    } catch (e) {
+      // .. if we can't read the file, forget
+      // about it for now.
+    }
+  }
+  try {
+    var dirs = fs.readdirSync(currentDirPath);
+    dirs.forEach(function (name) {
+      var filePath = path.join(currentDirPath, name);
+      readFile(filePath, callback);
+    });
+  } catch (e) {
+    if (e.code === 'ENOTDIR') {
+      readFile(currentDirPath, callback);
+    }
+  }
+};
\ No newline at end of file
diff --git a/packages/ls/dist/util/walkDirRecursive.js b/packages/ls/dist/util/walkDirRecursive.js
new file mode 100755
index 0000000..bc4be6d
--- /dev/null
+++ b/packages/ls/dist/util/walkDirRecursive.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Recursively walks through and executes
+ * a callback function for each directory found.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  fs.readdirSync(currentDirPath).forEach(function (name) {
+    var filePath = path.join(currentDirPath, name);
+    var stat = fs.statSync(filePath);
+    if (stat.isDirectory()) {
+      callback(filePath, stat);
+      module.exports(filePath, callback);
+    }
+  });
+};
\ No newline at end of file
diff --git a/packages/ls/package.json b/packages/ls/package.json
new file mode 100644
index 0000000..6cf1318
--- /dev/null
+++ b/packages/ls/package.json
@@ -0,0 +1,52 @@
+{
+  "name": "cash-ls",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'ls' command.",
+  "main": "./dist/commands/ls.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "ls": "./bin/ls.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "chalk": "^1.1.0",
+    "filesize": "^3.1.3",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/mkdir/README.md b/packages/mkdir/README.md
new file mode 100755
index 0000000..c385ed9
--- /dev/null
+++ b/packages/mkdir/README.md
@@ -0,0 +1,47 @@
+# cash-mkdir
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `mkdir` command.
+
+```bash
+npm install cash-mkdir -g
+```
+
+This will install `mkdir` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> mkdir --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/mkdir/bin/mkdir.js b/packages/mkdir/bin/mkdir.js
new file mode 100644
index 0000000..31f0387
--- /dev/null
+++ b/packages/mkdir/bin/mkdir.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mkdir');
diff --git a/packages/mkdir/bin/parser.js b/packages/mkdir/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/mkdir/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/mkdir/dist/commands/mkdir.js b/packages/mkdir/dist/commands/mkdir.js
new file mode 100755
index 0000000..8f92c96
--- /dev/null
+++ b/packages/mkdir/dist/commands/mkdir.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+
+var mkdir = {
+  exec: function exec(args, options) {
+    var self = this;
+    var dirs = args || [];
+    options = options || {};
+
+    if (typeof dirs === 'string') {
+      dirs = dirs.split(' ');
+    }
+
+    dirs = dirs.filter(function (str) {
+      return String(str).trim() !== '';
+    });
+
+    if (dirs.length < 1) {
+      this.log('mkdir: missing operand\nTry \'mkdir --help\' for more information.');
+    }
+
+    dirs.forEach(function (dir) {
+      if (fs.existsSync(dir)) {
+        if (!options.parents) {
+          self.log('mkdir: cannot create directory ' + dir + ': File exists');
+        }
+        return;
+      }
+
+      // Base dir does not exist, and no -p option given
+      var baseDir = path.dirname(dir);
+      if (!fs.existsSync(baseDir) && !options.parents) {
+        self.log('mkdir: cannot create directory ' + dir + ': No such file or directory');
+        return;
+      }
+
+      if (options.parents) {
+        mkdirSyncRecursive.call(self, dir, options);
+      } else {
+        fs.mkdirSync(dir, parseInt('0777', 8));
+        if (options.verbose) {
+          self.log('mkdir: created directory ' + dir);
+        }
+      }
+    });
+    return 0;
+  }
+};
+
+function mkdirSyncRecursive(dir, options) {
+  var baseDir = path.dirname(dir);
+  if (fs.existsSync(baseDir)) {
+    fs.mkdirSync(dir, parseInt('0777', 8));
+    if (options.verbose) {
+      this.log('mkdir: created directory ' + dir);
+    }
+    return;
+  }
+  mkdirSyncRecursive.call(this, baseDir, options);
+  fs.mkdirSync(dir, parseInt('0777', 8));
+  if (options.verbose) {
+    this.log('mkdir: created directory ' + dir);
+  }
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mkdir;
+  }
+  vorpal.api.mkdir = mkdir;
+  vorpal.command('mkdir [directory...]').option('-p, --parents', 'no error if existing, make parent directories as needed').option('-v, --verbose', 'print a message for each created directory').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+    args.options = args.options || {};
+    args.options.vorpal = vorpal;
+    return interfacer.call(this, {
+      command: mkdir,
+      args: args.directory,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/mkdir/dist/help/mkdir.js b/packages/mkdir/dist/help/mkdir.js
new file mode 100755
index 0000000..6ffa2cd
--- /dev/null
+++ b/packages/mkdir/dist/help/mkdir.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mkdir [OPTION]... DIRECTORY...\nCreate the DIRECTORY(ies), if they do not already exist.\n\n  -p, --parents     no error if existing, make parent directories as needed\n  -v, --verbose     print a message for each created directory\n      --help        display this help and exit\n\nReport mkdir bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/mkdir/dist/util/interfacer.js b/packages/mkdir/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/mkdir/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/mkdir/package.json b/packages/mkdir/package.json
new file mode 100644
index 0000000..82ac424
--- /dev/null
+++ b/packages/mkdir/package.json
@@ -0,0 +1,49 @@
+{
+  "name": "cash-mkdir",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'mkdir' command.",
+  "main": "./dist/commands/mkdir.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "mkdir": "./bin/mkdir.js"
+  },
+  "dependencies": {
+    "vorpal-autocomplete-fs": "0.0.3",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/mv/README.md b/packages/mv/README.md
new file mode 100755
index 0000000..b32dbd2
--- /dev/null
+++ b/packages/mv/README.md
@@ -0,0 +1,47 @@
+# cash-mv
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `mv` command.
+
+```bash
+npm install cash-mv -g
+```
+
+This will install `mv` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> mv --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/mv/bin/mv.js b/packages/mv/bin/mv.js
new file mode 100644
index 0000000..298c101
--- /dev/null
+++ b/packages/mv/bin/mv.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mv');
diff --git a/packages/mv/bin/parser.js b/packages/mv/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/mv/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/mv/dist/commands/mv.js b/packages/mv/dist/commands/mv.js
new file mode 100755
index 0000000..9a79232
--- /dev/null
+++ b/packages/mv/dist/commands/mv.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var mv = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+
+    args = args === undefined ? [] : args;
+    args = _.isArray(args) ? args : args.split(' ');
+    args = _.filter(args, function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    options.noclobber = options.force === true ? false : options.noclobber;
+
+    if (args.length < 1) {
+      this.log('mv: missing file operand\nTry \'mv --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log('mv: missing destination file operand after ' + args[0] + '\nTry \'mv --help\' for more information.');
+      return 1;
+    }
+
+    args = expand(args);
+
+    var dest = args.pop();
+    var sources = args;
+
+    var exists = fs.existsSync(dest);
+    var stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log('mv: target ' + dest + ' is not a directory');
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.striptrailingslashes) {
+      sources = sources.map(function (src) {
+        return String(src).replace(/\/$/g, '');
+      });
+    }
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log('mv: cannot stat ' + src + ': No such file or directory');
+        return;
+      }
+
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      var iDest = dest;
+      if (exists && stats.isDirectory()) {
+        iDest = path.normalize(dest + '/' + path.basename(src));
+      }
+
+      // If the file exists and we're not clobbering, skip.
+      if (fs.existsSync(iDest) && options.noclobber) {
+        return;
+      }
+
+      if (path.resolve(src) === path.dirname(path.resolve(iDest))) {
+        self.log('mv: ' + src + ' and ' + iDest + ' are the same file');
+        return;
+      }
+
+      fs.renameSync(src, iDest);
+      if (options.verbose === true) {
+        self.log(String(src + ' -> ' + iDest).replace(/\\/g, '/'));
+      }
+    });
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mv;
+  }
+  vorpal.api.mv = mv;
+  vorpal.command('mv [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('--striptrailingslashes', 'remove any trailing slashes from each source') // vorpal bug, need to add dashes between words
+  .option('-v, --verbose', 'explain what is being done').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: mv,
+      args: args.args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/mv/dist/help/mv.js b/packages/mv/dist/help/mv.js
new file mode 100755
index 0000000..a368bf1
--- /dev/null
+++ b/packages/mv/dist/help/mv.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mv [OPTION]... [-T] SOURCE DEST\n  or:  mv [OPTION]... SOURCE... DIRECTORY\n  or:  mv [OPTION]... -t DIRECTORY SOURCE...\nRename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n  -f, --force                  do not prompt before overwriting\n  -n, --no-clobber             do not overwrite an existing file\n      --striptrailingslashes   remove any trailing slashes from each SOURCE\n                                 argument\n  -v, --verbose                explain what is being done\n      --help                   display this help and exit\n\nIf you specify -f and -n, only -f takes effect.\n\nReport mv bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/mv/dist/util/expand.js b/packages/mv/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/packages/mv/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/packages/mv/dist/util/interfacer.js b/packages/mv/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/mv/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/mv/package.json b/packages/mv/package.json
new file mode 100644
index 0000000..ce0f369
--- /dev/null
+++ b/packages/mv/package.json
@@ -0,0 +1,51 @@
+{
+  "name": "cash-mv",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'mv' command.",
+  "main": "./dist/commands/mv.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "mv": "./bin/mv.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "glob": "^6.0.4",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/pwd/README.md b/packages/pwd/README.md
new file mode 100755
index 0000000..7f06d13
--- /dev/null
+++ b/packages/pwd/README.md
@@ -0,0 +1,47 @@
+# cash-pwd
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `pwd` command.
+
+```bash
+npm install cash-pwd -g
+```
+
+This will install `pwd` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> pwd --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/pwd/bin/parser.js b/packages/pwd/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/pwd/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/pwd/bin/pwd.js b/packages/pwd/bin/pwd.js
new file mode 100644
index 0000000..367f6e8
--- /dev/null
+++ b/packages/pwd/bin/pwd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'pwd');
diff --git a/packages/pwd/dist/commands/pwd.js b/packages/pwd/dist/commands/pwd.js
new file mode 100755
index 0000000..b46eca7
--- /dev/null
+++ b/packages/pwd/dist/commands/pwd.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var path = require('path');
+
+var interfacer = require('./../util/interfacer');
+
+var pwd = {
+  exec: function exec() {
+    this.log(path.resolve(process.cwd()).replace(/\\/g, '/'));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return pwd;
+  }
+  vorpal.api.pwd = pwd;
+  vorpal.command('pwd [files...]').action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: pwd,
+      args: args.files,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/pwd/dist/help/pwd.js b/packages/pwd/dist/help/pwd.js
new file mode 100755
index 0000000..2db3568
--- /dev/null
+++ b/packages/pwd/dist/help/pwd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: pwd [-LP]\nPrint the name of the current working directory.\n\n      --help        display this help and exit\n\nExit status:\n  0   if OK,\n  1   if an invalid option is given or the current directory\n      cannot be read.\n\nReport pwd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/pwd/dist/util/interfacer.js b/packages/pwd/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/pwd/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/pwd/package.json b/packages/pwd/package.json
new file mode 100644
index 0000000..0599ca6
--- /dev/null
+++ b/packages/pwd/package.json
@@ -0,0 +1,48 @@
+{
+  "name": "cash-pwd",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'pwd' command.",
+  "main": "./dist/commands/pwd.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "pwd": "./bin/pwd.js"
+  },
+  "dependencies": {
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/rm/README.md b/packages/rm/README.md
new file mode 100755
index 0000000..a6dc538
--- /dev/null
+++ b/packages/rm/README.md
@@ -0,0 +1,47 @@
+# cash-rm
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `rm` command.
+
+```bash
+npm install cash-rm -g
+```
+
+This will install `rm` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> rm --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/rm/bin/parser.js b/packages/rm/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/rm/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/rm/bin/rm.js b/packages/rm/bin/rm.js
new file mode 100644
index 0000000..0bb6783
--- /dev/null
+++ b/packages/rm/bin/rm.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'rm');
diff --git a/packages/rm/dist/commands/rm.js b/packages/rm/dist/commands/rm.js
new file mode 100755
index 0000000..502f359
--- /dev/null
+++ b/packages/rm/dist/commands/rm.js
@@ -0,0 +1,171 @@
+'use strict';
+
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+var unlinkSync = require('./../util/unlinkSync');
+
+var rm = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+    options.recursive = options.R ? options.R : options.recursive;
+
+    var files = args;
+    files = files === undefined ? [] : files;
+    files = typeof files === 'string' ? [files] : files;
+
+    files = expand(files);
+
+    files.forEach(function (file) {
+      if (!fs.existsSync(file)) {
+        // Path does not exist, no force flag given
+        if (!options.force) {
+          self.log('rm: cannot remove ' + file + ': No such file or directory');
+          return 2;
+        }
+        /* istanbul ignore next */
+        return 0;
+      }
+
+      var stats = fs.lstatSync(file);
+      if (stats.isFile() || stats.isSymbolicLink()) {
+        if (options.force) {
+          unlinkSync(file);
+          return 0;
+        }
+
+        if (isWriteable(file)) {
+          unlinkSync(file);
+        } else {
+          /* istanbul ignore next */
+          self.log('rm: cannot remove ' + file + ': permission denied');
+          /* istanbul ignore next */
+          return 2;
+        }
+        return 0;
+      }
+
+      // Path is an existing directory, but no -r flag given
+      if (stats.isDirectory() && !options.recursive) {
+        self.log('rm: cannot remove: path is a directory');
+        return 2;
+      }
+
+      // Recursively remove existing directory
+      if (stats.isDirectory() && options.recursive) {
+        rmdirSyncRecursive.call(self, file, options.force, options.dir);
+      }
+    });
+  }
+};
+
+function rmdirSyncRecursive(dir, force, removeEmptyDir) {
+  var self = this;
+  var files = undefined;
+  files = fs.readdirSync(dir);
+
+  // Loop through and delete everything in the sub-tree after checking it
+  for (var i = 0; i < files.length; i++) {
+    var file = dir + '/' + files[i];
+    var currFile = fs.lstatSync(file);
+
+    if (currFile.isDirectory()) {
+      // Recursive function back to the beginning
+      rmdirSyncRecursive(file, force, removeEmptyDir);
+    } else if (currFile.isSymbolicLink()) {
+      // Unlink symlinks
+      /* istanbul ignore next */
+      if (force || isWriteable(file)) {
+        try {
+          unlinkSync(file);
+        } catch (e) {
+          self.log('rm: cannot remove ' + file + ': code ' + e.code);
+          return 2;
+        }
+      }
+    } else if (force || isWriteable(file)) {
+      // Assume it's a file.
+      try {
+        unlinkSync(file);
+      } catch (e) {
+        /* istanbul ignore next */
+        self.log('rm: cannot remove ' + file + ': code ' + e.code);
+        /* istanbul ignore next */
+        return 2;
+      }
+    }
+  }
+
+  // Now that we know everything in the sub-tree has been deleted,
+  // we can delete the main directory.
+  var result = undefined;
+  try {
+    // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+    var start = Date.now();
+    while (true) {
+      try {
+        result = fs.rmdirSync(dir);
+        /* istanbul ignore next */
+        if (fs.existsSync(dir)) {
+          throw new Error('EAGAIN');
+        }
+        break;
+      } catch (er) {
+        // In addition to error codes, also check if the directory still exists and loop again if true
+        /* istanbul ignore next */
+        if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+          if (Date.now() - start > 1000) {
+            throw er;
+          }
+          /* istanbul ignore next */
+        } else if (er.code === 'ENOENT') {
+            // Directory did not exist, deletion was successful
+            break;
+            /* istanbul ignore next */
+          } else {
+              throw er;
+            }
+      }
+    }
+  } catch (e) {
+    /* istanbul ignore next */
+    self.log('rm: cannot remove directory ' + dir + ': code ' + e.code);
+    /* istanbul ignore next */
+    return 2;
+  }
+  return result;
+}
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow.
+function isWriteable(file) {
+  var writePermission = true;
+  try {
+    var __fd = fs.openSync(file, 'a');
+    fs.closeSync(__fd);
+  } catch (e) {
+    /* istanbul ignore next */
+    writePermission = false;
+  }
+
+  return writePermission;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return rm;
+  }
+  vorpal.api.rm = rm;
+  vorpal.command('rm [files...]').option('-f, --force', 'ignore nonexistent files and arguments, never prompt').option('-r, --recursive', 'remove directories and their contents recursively').option('-R', 'remove directories and their contents recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: rm,
+      args: args.files,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/rm/dist/help/rm.js b/packages/rm/dist/help/rm.js
new file mode 100755
index 0000000..85b4474
--- /dev/null
+++ b/packages/rm/dist/help/rm.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: rm [OPTION]... FILE...\nRemove (unlink) the FILE(s).\n\n  -f, --force           ignore nonexistent files and arguments, never prompt\n  -r, -R, --recursive   remove directories and their contents recursively\n      --help            display this help and exit\n\nBy default, rm does not remove directories.  Use the --recursive (-r or -R)\noption to remove each listed directory, too, along with all of its contents.\n\nTo remove a file whose name starts with a '-', for example '-foo',\nuse one of these commands:\n  rm -- -foo\n  rm ./-foo\n\nNote that if you use rm to remove a file, it might be possible to recover\nsome of its contents, given sufficient expertise and/or time.\n\nReport rm bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/rm/dist/util/expand.js b/packages/rm/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/packages/rm/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/packages/rm/dist/util/interfacer.js b/packages/rm/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/rm/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/rm/dist/util/unlinkSync.js b/packages/rm/dist/util/unlinkSync.js
new file mode 100755
index 0000000..784fb7d
--- /dev/null
+++ b/packages/rm/dist/util/unlinkSync.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var fs = require('fs');
+
+/**
+ * Normalizes _unlinkSync() across
+ * platforms to match Unix behavior, i.e.
+ * file can be unlinked even its it's
+ * read only.
+ * See https://github.com/joyent/node/issues/3006
+ *
+ * @param {String} file
+ * @api public
+ */
+
+module.exports = function (file) {
+  try {
+    fs.unlinkSync(file);
+  } catch (e) {
+    // Try to override file permission
+    /* istanbul ignore if */
+    if (e.code === 'EPERM') {
+      fs.chmodSync(file, '0666');
+      fs.unlinkSync(file);
+    } else {
+      /* istanbul ignore next */
+      throw e;
+    }
+  }
+};
\ No newline at end of file
diff --git a/packages/rm/package.json b/packages/rm/package.json
new file mode 100644
index 0000000..183a2c6
--- /dev/null
+++ b/packages/rm/package.json
@@ -0,0 +1,50 @@
+{
+  "name": "cash-rm",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'rm' command.",
+  "main": "./dist/commands/rm.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "rm": "./bin/rm.js"
+  },
+  "dependencies": {
+    "vorpal-autocomplete-fs": "0.0.3",
+    "glob": "^6.0.4",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/sort/README.md b/packages/sort/README.md
new file mode 100755
index 0000000..16cb1a7
--- /dev/null
+++ b/packages/sort/README.md
@@ -0,0 +1,47 @@
+# cash-sort
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `sort` command.
+
+```bash
+npm install cash-sort -g
+```
+
+This will install `sort` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> sort --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/sort/bin/parser.js b/packages/sort/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/sort/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/sort/bin/sort.js b/packages/sort/bin/sort.js
new file mode 100644
index 0000000..ec3a025
--- /dev/null
+++ b/packages/sort/bin/sort.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'sort');
diff --git a/packages/sort/dist/commands/sort.js b/packages/sort/dist/commands/sort.js
new file mode 100755
index 0000000..0212ca0
--- /dev/null
+++ b/packages/sort/dist/commands/sort.js
@@ -0,0 +1,269 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var strip = require('./../util/stripAnsi');
+
+var sort = {
+
+  counter: 0,
+
+  stdin: '',
+
+  exec: function exec(args, options) {
+    var self = this;
+
+    // Hack to handle multiple calls
+    // due to fragmented stdin, such as
+    // by piping. In essence, we're waiting
+    // 100 milliseconds for all of the
+    // requests to come in, and then running
+    // sort. Only applies when sort is called
+    // through a piped command.
+    /* istanbul ignore next */
+    if (args && args.stdin && options.bypass !== true) {
+      sort.counter++;
+      sort.stdin += args.stdin + '\n';
+      if (sort.counter === 1) {
+        setTimeout(function () {
+          sort.counter = 0;
+          args.stdin = sort.stdin;
+          sort.stdin = '';
+          options.bypass = true;
+          sort.exec.call(self, args, options);
+        }, 100);
+      }
+      return;
+    }
+    sort.counter = 0;
+    sort.stdin = '';
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    function log(stdout) {
+      if (options.output) {
+        if (options.output === true) {
+          self.log('sort: option \'--output\' requires an argument\nTry \'sort --help\' for more information.');
+          return 0;
+        }
+        try {
+          fs.writeFileSync(options.output, stdout);
+          return 0;
+        } catch (e) {
+          if (e.code === 'ENOENT') {
+            self.log('sort: open failed: ' + options.output + ': No such file or directory');
+          } else {
+            /* istanbul ignore next */
+            self.log('sort: open failed: ' + options.output + ': ' + e.code);
+          }
+          return 2;
+        }
+      } else {
+        self.log(stdout);
+      }
+    }
+
+    try {
+      var stdin = fetch(args.files, args.stdin, {
+        onDirectory: function onDirectory(name) {
+          /* istanbul ignore next */
+          return 'sort: read failed: ' + name + ': Is a directory';
+        },
+        onInvalidFile: function onInvalidFile(name) {
+          /* istanbul ignore next */
+          return 'sort: cannot read: ' + name + ': No such file or directory';
+        }
+      });
+
+      var combined = '';
+      for (var i = 0; i < stdin.length; ++i) {
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        combined += stdin[i];
+      }
+
+      combined = combined.replace(/\s$/, '');
+      var parts = String(combined).split('\n');
+
+      if (options.check) {
+        // Check if the thing was already sorted.
+        var original = String(combined).split('\n');
+        var disorder = undefined;
+        for (var i = 0; i < original.length; ++i) {
+          var a = original[i];
+          var b = original[i + 1];
+          if (a && b) {
+            if (!isNaN(a) && !isNaN(b) && parseFloat(a) > parseFloat(b)) {
+              /* istanbul ignore next */
+              disorder = true;
+            } else if (a > b) {
+              disorder = true;
+            }
+            if (disorder) {
+              // To do: right now, I don't say the file
+              // name of the bad sorted item - I have to
+              // figure this out as I join all the files
+              // together beforehand and lose track.
+              disorder = 'sort: -:' + (i + 2) + ': disorder: ' + b;
+              break;
+            }
+          }
+        }
+        if (disorder) {
+          log(disorder);
+          return;
+        }
+      }
+
+      parts = parts.sort(function (a, b) {
+        var aAlpha = strip(a).replace(/\W+/g, '');
+        var bAlpha = strip(b).replace(/\W+/g, '');
+        var aNumeric = strip(a).replace(/\D/g, '');
+        var bNumeric = strip(b).replace(/\D/g, '');
+        if (options.humannumericsort) {
+          var aHuman = parseHumanReadableNumbers(strip(a));
+          var bHuman = parseHumanReadableNumbers(strip(b));
+          if (aHuman.group < bHuman.group) {
+            return -1;
+          } else if (aHuman.group > bHuman.group) {
+            return 1;
+          } else if (aHuman.num < bHuman.num) {
+            return -1;
+          } else if (aHuman.num > bHuman.num) {
+            return 1;
+          }
+          return aAlpha.localeCompare(bAlpha);
+        } else if (options.monthsort) {
+          var aMonth = parseMonths(strip(a));
+          var bMonth = parseMonths(strip(b));
+          var result = aMonth - bMonth;
+          if (aMonth === bMonth) {
+            result = aAlpha.localeCompare(bAlpha);
+          }
+          return result;
+        } else if (options.numericsort) {
+          var result = aNumeric - bNumeric;
+          result = result === 0 ? aAlpha.localeCompare(bAlpha) : result;
+          return result;
+        }
+        return aAlpha.localeCompare(bAlpha);
+      });
+
+      if (options.randomsort) {
+        fisherYatesShuffle(parts);
+      }
+
+      if (options.reverse) {
+        parts.reverse();
+      }
+
+      var out = parts.join('\n');
+      if (String(out).trim() !== '') {
+        log(out);
+      }
+
+      return;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return;
+    }
+  }
+};
+
+// This shit is gnarly.
+// Per the coreutils sort.c:
+// <none/unknown> < K/k < M < G < T < P < E < Z < Y
+var humanOrdering = { '': 0, 'K': 1, 'k': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7 };
+var humanReadableSort = new RegExp(/^([0-9]+)?[\.]?[0-9]+[K|k|M|G|T|P|E|Z|Y]/g);
+function parseHumanReadableNumbers(nbr) {
+  nbr = String(nbr).replace(/(\r\n|\n|\r)/gm, '');
+  if (String(nbr).match(humanReadableSort)) {
+    var num = parseFloat(String(nbr).replace(/[a-zA-Z]/g, '').trim());
+    var group = humanOrdering[String(nbr).replace(/[^a-zA-Z]/g, '').trim()] || 0;
+    return {
+      num: num,
+      group: group
+    };
+  }
+  var isNumber = String(nbr).match(/^[0-9]/);
+  var stripped = isNumber ? parseFloat(String(nbr).replace(/[^0-9.]/g, '')) : 'NaN';
+  var result = !isNaN(stripped) ? stripped : -99999999999;
+  return {
+    num: result,
+    group: 0
+  };
+}
+
+var monthOrdering = {
+  jan: 1,
+  feb: 2,
+  mar: 3,
+  apr: 4,
+  may: 5,
+  jun: 6,
+  jul: 7,
+  aug: 8,
+  sep: 9,
+  oct: 10,
+  nov: 11,
+  dec: 12
+};
+
+var months = new RegExp(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i);
+function parseMonths(str) {
+  var match = String(str).match(months);
+  if (match) {
+    return monthOrdering[String(str.slice(0, 3).toLowerCase())];
+  }
+  return 0;
+}
+
+function fisherYatesShuffle(array) {
+  var m = array.length;
+  var t = undefined;
+  var i = undefined;
+  while (m) {
+    i = Math.floor(Math.random() * m--);
+    t = array[m];
+    array[m] = array[i];
+    array[i] = t;
+  }
+  return array;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return sort;
+  }
+  vorpal.api.sort = sort;
+  vorpal.command('sort [files...]').option('-M, --month-sort', 'compare (unknown) < \'JAN\' < ... < \'DEC\'').option('-h, --human-numeric-sort', 'compare human readable numbers (e.g., 2K 1G)').option('-n, --numeric-sort', 'compare according to string numerical value').option('-R, --random-sort', 'sort by random hash of keys').option('-r, --reverse', 'reverse the result of comparisons').option('-c, --check', 'check for sorted input; do not sort').option('-o, --output [file]', 'write result to file instead of standard output').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: sort,
+      args: args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/sort/dist/help/sort.js b/packages/sort/dist/help/sort.js
new file mode 100755
index 0000000..6e59482
--- /dev/null
+++ b/packages/sort/dist/help/sort.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: sort [OPTION]... [FILE]...\nWrite sorted concatenation of all FILE(s) to standard output.\n\nOrdering options:\n  -M, --month-sort            compare (unknown) < 'JAN' < ... < 'DEC'\n  -h, --human-numeric-sort    compare human readable numbers (e.g., 2K 1G)\n  -n, --numeric-sort          compare according to string numerical value\n  -R, --random-sort           sort by random hash of keys\n  -r, --reverse               reverse the result of comparisons\n\nOther options:\n  -c, --check,\n      --check=diagnose-first  check for sorted input; do not sort\n  -o, --output=FILE           write result to FILE instead of standard output\n      --help                  display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nReport sort bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/sort/dist/util/expand.js b/packages/sort/dist/util/expand.js
new file mode 100755
index 0000000..49e12a5
--- /dev/null
+++ b/packages/sort/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  var total = list.length;
+  var files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (var i = 0; i < total; ++i) {
+    var res = glob.sync(list[i], {});
+    files[i] = res.length > 0 ? res : list[i];
+  }
+  var out = [];
+  for (var i = 0; i < files.length; ++i) {
+    out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+  }
+  return out;
+};
\ No newline at end of file
diff --git a/packages/sort/dist/util/fetch.js b/packages/sort/dist/util/fetch.js
new file mode 100755
index 0000000..da862df
--- /dev/null
+++ b/packages/sort/dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+  files = files || [];
+  stdin = stdin !== undefined ? stdin : [];
+  var f = expand(files);
+
+  if (!(f.length === 0 && files.length > 0)) {
+    files = f;
+  }
+
+  for (var i = 0; i < files.length; ++i) {
+    try {
+      var stat = fs.statSync(files[i]);
+      if (stat.isDirectory()) {
+        files[i] = options.onDirectory(files[i]);
+      } else {
+        files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+      }
+    } catch (e) {
+      files[i] = options.onInvalidFile(files[i]);
+    }
+  }
+
+  var agg = files.length < 1 ? stdin : files;
+  var final = [];
+
+  for (var i = 0; i < agg.length; ++i) {
+    if (agg[i] !== undefined) {
+      final.push(agg[i]);
+    }
+  }
+  return final;
+};
\ No newline at end of file
diff --git a/packages/sort/dist/util/interfacer.js b/packages/sort/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/sort/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/sort/dist/util/stripAnsi.js b/packages/sort/dist/util/stripAnsi.js
new file mode 100755
index 0000000..e05149e
--- /dev/null
+++ b/packages/sort/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+  var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+  return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
\ No newline at end of file
diff --git a/packages/sort/package.json b/packages/sort/package.json
new file mode 100644
index 0000000..e470e03
--- /dev/null
+++ b/packages/sort/package.json
@@ -0,0 +1,51 @@
+{
+  "name": "cash-sort",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'sort' command.",
+  "main": "./dist/commands/sort.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "sort": "./bin/sort.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "glob": "^6.0.4",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/packages/template.README.md b/packages/template.README.md
new file mode 100755
index 0000000..1a8a2a6
--- /dev/null
+++ b/packages/template.README.md
@@ -0,0 +1,32 @@
+# {package-name}
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `{command-name}` command.
+
+```bash
+npm install {package-name} -g
+```
+
+This will install `{command-name}` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> {command-name} --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+{related}
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/template.package.json b/packages/template.package.json
new file mode 100755
index 0000000..4778efe
--- /dev/null
+++ b/packages/template.package.json
@@ -0,0 +1,44 @@
+{
+  "name": "",
+  "version": "0.0.1",
+  "description": "",
+  "main": "",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {},
+  "dependencies": {},
+  "engines": {
+    "node": ">= 4",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
\ No newline at end of file
diff --git a/packages/touch/README.md b/packages/touch/README.md
new file mode 100755
index 0000000..db7b600
--- /dev/null
+++ b/packages/touch/README.md
@@ -0,0 +1,47 @@
+# cash-touch
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `touch` command.
+
+```bash
+npm install cash-touch -g
+```
+
+This will install `touch` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> touch --help
+```
+
+## More
+
+This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript.
+
+
+## Related
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
diff --git a/packages/touch/bin/parser.js b/packages/touch/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/touch/bin/parser.js
@@ -0,0 +1,50 @@
+'use strict';
+
+module.exports = function (args, command) {
+  args.splice(0, 2);
+  var pipes = (args.indexOf('|') > -1);
+  if (args.length === 0) {
+    // If we don't have to parse arguments, do
+    // the quickest load: just the raw js file
+    // of the command and nothing else.
+    var cmd = require('./../dist/commands/' + command)();
+    cmd.exec.call(console, {options: {}}, {});
+  } else if (pipes === false) {
+    // If we need to parse args for this
+    // command only, pull up vorpal and just load
+    // that one command.
+    var vorpal = require('vorpal')();
+    vorpal.api = {};
+    require('./../dist/commands/' + command)(vorpal);
+    args = args.join(' ');
+
+    // If we passed in a help request, load in
+    // the help file.
+    if (args.indexOf('help') > -1 || args.indexOf('?') > -1) {
+      let help;
+      try {
+        help = require('./../dist/help/' + command + '.js');
+        help = String(help).replace(/^\n|\n$/g, '');
+      } catch (e) {}
+      let cmdObj = vorpal.find(command);
+      if (cmdObj && help) {
+        cmdObj.help(function (argus, cb) {
+          cb(help);
+        })
+      }
+    }
+    vorpal.exec(command + ' ' + args);
+  } else {
+    // If we get into piping other commands,
+    // we need to go full bore and load the
+    // entire cash library.
+    // I guess we could technically parse all
+    // of the passed args, look for applicable
+    // commands and only load those, but that's
+    // some messy work for something that might
+    // not matter. If you're reading this and
+    // have deemed it matters, do a PR.
+    var cash = require('./../dist/index');
+    cash.vorpal.exec(command + ' ' + args.join(' '));
+  }
+};
diff --git a/packages/touch/bin/touch.js b/packages/touch/bin/touch.js
new file mode 100644
index 0000000..89f8d6e
--- /dev/null
+++ b/packages/touch/bin/touch.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'touch');
diff --git a/packages/touch/dist/commands/touch.js b/packages/touch/dist/commands/touch.js
new file mode 100755
index 0000000..d8b07cb
--- /dev/null
+++ b/packages/touch/dist/commands/touch.js
@@ -0,0 +1,151 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs-extra');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+require('./../lib/sugar');
+
+var touch = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec: function exec(files, options) {
+    var self = this;
+    files = files || ['.'];
+    files = !_.isArray(files) ? [files] : files;
+    options = options || {};
+
+    // If any version of --no-create is passed, change it to false.
+    options.create = options.create === true ? false : options.create;
+
+    // If --time is passed, ensure a valid param is called in
+    // and map it to -a or -m, as this is the equivalent of these.
+    // Throw an error if nothing valid passed.
+    if (options.time) {
+      var a = ['access', 'atime', 'use'];
+      var m = ['modify', 'mtime'];
+      var opt = a.indexOf(options.time) > -1 ? 'a' : m.indexOf(options.time) > -1 ? 'm' : undefined;
+      if (!opt) {
+        var error = 'touch: invalid argument "' + options.time + '" for "--time"\n' + 'Valid arguments are:\n' + '  - "atime", "access", "use"\n' + '  - "mtime", "modify"\n' + 'Try \'touch --help\' for more information.';
+        // I think this is the stupidest thing
+        // I've ever written.
+        try {
+          throw new Error(error);
+        } catch (e) {
+          return touch.error.call(self, e);
+        }
+      } else {
+        options[opt] = true;
+      }
+    }
+
+    try {
+      var err = false;
+      for (var i = 0; i < files.length; ++i) {
+        try {
+          touch.file(files[i], options);
+        } catch (e) {
+          err = e;
+          break;
+        }
+      }
+      if (err) {
+        return touch.error.call(self, err);
+      }
+      return 0;
+    } catch (e) {
+      return touch.error.call(self, e);
+    }
+  },
+
+  /**
+   * Returns touch stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error: function error(e) {
+    this.log(e.message);
+    return 2;
+  },
+
+  /**
+   * Handler for a single file using touch.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @api private
+   */
+
+  file: function file(path, options) {
+    try {
+      try {
+        fs.lstatSync(path);
+      } catch (e) {
+        // If the file doesn't exist and
+        // the user doesn't want to create it,
+        // we have no purpose in life. Goodbye.
+        if (options.create === false) {
+          throw new Error(e);
+        } else {
+          fs.closeSync(fs.openSync(path, 'wx'));
+        }
+      }
+
+      var stat = fs.statSync(path);
+      var dateToSet = options.date ? Date.create(options.date) : new Date();
+
+      if (String(dateToSet) === 'Invalid Date') {
+        throw new Error('touch: invalid date format ' + options.date);
+      }
+
+      // If -m, keep access time current.
+      var atime = options.m === true ? new Date(stat.atime) : dateToSet;
+
+      // If -a, keep mod time to current.
+      var mtime = options.a === true ? new Date(stat.mtime) : dateToSet;
+
+      if (options.reference !== undefined) {
+        var reference = undefined;
+        try {
+          reference = fs.statSync(options.reference);
+        } catch (e) {
+          throw new Error('touch: failed to get attributes of ' + options.reference + ': No such file or directory');
+        }
+        atime = options.m === true ? atime : reference.atime;
+        mtime = options.a === true ? mtime : reference.mtime;
+      }
+
+      fs.utimesSync(path, atime, mtime);
+      fs.utimesSync(path, atime, mtime);
+    } catch (e) {
+      throw new Error(e);
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return touch;
+  }
+  vorpal.api.touch = touch;
+  vorpal.command('touch <files...>').option('-a', 'change only the access time').option('-c, --no-create', 'do not create any files').option('-d, --date [STRING]', 'parse STRING and use it instead of current time').option('-m', 'change only the modification time').option('-r, --reference [FILE]', 'use this file\'s times instead of current time').option('--time [WORD]', 'change the specified time: WORD is access, atime, or use: equivalent to -a WORD is modify or mtime: equivalent to -m').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    return interfacer.call(this, {
+      command: touch,
+      args: args.files || [],
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/packages/touch/dist/help/touch.js b/packages/touch/dist/help/touch.js
new file mode 100755
index 0000000..3f2d444
--- /dev/null
+++ b/packages/touch/dist/help/touch.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: touch [OPTION]... FILE...\nUpdate the access and modification times of each FILE to the current time.\n\nA FILE argument that does not exist is created empty, unless -c is\nsupplied.\n\n  -a                      change only the access time\n  -c, --no-create         do not create any files\n  -d, --date <STRING>     parse STRING and use it instead of current time\n  -m                      change only the modification time\n  -r, --reference <FILE>  use this file's times instead of current time\n      --time <WORD>       change the specified time:\n                            WORD is access, atime, or use: equivalent to -a\n                            WORD is modify or mtime: equivalent to -m\n      --help              display this help and exit\n\nReport touch bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
\ No newline at end of file
diff --git a/packages/touch/dist/lib/sugar.js b/packages/touch/dist/lib/sugar.js
new file mode 100755
index 0000000..ffee6c5
--- /dev/null
+++ b/packages/touch/dist/lib/sugar.js
@@ -0,0 +1,747 @@
+"use strict";
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+/*
+ *  Sugar Library v1.4.1
+ *
+ *  Freely distributable and licensed under the MIT-style license.
+ *  Copyright (c) 2014 Andrew Plummer
+ *  http://sugarjs.com/
+ *
+ * ---------------------------- */
+/* istanbul ignore next */
+(function () {
+  function aa(a) {
+    return function () {
+      return a;
+    };
+  }
+  /* istanbul ignore next */
+  var m = Object,
+      p = Array,
+      q = RegExp,
+      r = Date,
+      s = String,
+      t = Number,
+      u = Math,
+      ba = "undefined" !== typeof global ? global : this,
+      v = m.prototype.toString,
+      da = m.prototype.hasOwnProperty,
+      ea = m.defineProperty && m.defineProperties,
+      fa = "function" === typeof q(),
+      ga = !("0" in new s("a")),
+      ia = {},
+      ja = /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,
+      w = "Boolean Number String Array Date RegExp Function".split(" "),
+      la = ka("boolean", w[0]),
+      y = ka("number", w[1]),
+      z = ka("string", w[2]),
+      A = ma(w[3]),
+      C = ma(w[4]),
+      D = ma(w[5]),
+      F = ma(w[6]);
+  /* istanbul ignore next */
+  function ma(a) {
+    var b = "Array" === a && p.isArray || function (b, d) {
+      return (d || v.call(b)) === "[object " + a + "]";
+    };return ia[a] = b;
+  }function ka(a, b) {
+    function c(c) {
+      return G(c) ? v.call(c) === "[object " + b + "]" : (typeof c === "undefined" ? "undefined" : _typeof(c)) === a;
+    }return ia[b] = c;
+  }
+  function na(a) {
+    a.SugarMethods || (oa(a, "SugarMethods", {}), H(a, !1, !0, { extend: function extend(b, c, d) {
+        H(a, !1 !== d, c, b);
+      }, sugarRestore: function sugarRestore() {
+        return pa(this, a, arguments, function (a, c, d) {
+          oa(a, c, d.method);
+        });
+      }, sugarRevert: function sugarRevert() {
+        return pa(this, a, arguments, function (a, c, d) {
+          d.existed ? oa(a, c, d.original) : delete a[c];
+        });
+      } }));
+  }function H(a, b, c, d) {
+    var e = b ? a.prototype : a;na(a);I(d, function (d, f) {
+      var h = e[d],
+          l = J(e, d);F(c) && h && (f = qa(h, f, c));!1 === c && h || oa(e, d, f);a.SugarMethods[d] = { method: f, existed: l, original: h, instance: b };
+    });
+  }
+  function K(a, b, c, d, e) {
+    var g = {};d = z(d) ? d.split(",") : d;d.forEach(function (a, b) {
+      e(g, a, b);
+    });H(a, b, c, g);
+  }function pa(a, b, c, d) {
+    var e = 0 === c.length,
+        g = L(c),
+        f = !1;I(b.SugarMethods, function (b, c) {
+      if (e || -1 !== g.indexOf(b)) f = !0, d(c.instance ? a.prototype : a, b, c);
+    });return f;
+  }function qa(a, b, c) {
+    return function (d) {
+      return c.apply(this, arguments) ? b.apply(this, arguments) : a.apply(this, arguments);
+    };
+  }function oa(a, b, c) {
+    ea ? m.defineProperty(a, b, { value: c, configurable: !0, enumerable: !1, writable: !0 }) : a[b] = c;
+  }
+  function L(a, b, c) {
+    var d = [];c = c || 0;var e;for (e = a.length; c < e; c++) {
+      d.push(a[c]), b && b.call(a, a[c], c);
+    }return d;
+  }function sa(a, b, c) {
+    var d = a[c || 0];A(d) && (a = d, c = 0);L(a, b, c);
+  }function ta(a) {
+    if (!a || !a.call) throw new TypeError("Callback is not callable");
+  }function M(a) {
+    return void 0 !== a;
+  }function N(a) {
+    return void 0 === a;
+  }function J(a, b) {
+    return !!a && da.call(a, b);
+  }function G(a) {
+    return !!a && ("object" === (typeof a === "undefined" ? "undefined" : _typeof(a)) || fa && D(a));
+  }function ua(a) {
+    var b = typeof a === "undefined" ? "undefined" : _typeof(a);return null == a || "string" === b || "number" === b || "boolean" === b;
+  }
+  function va(a, b) {
+    b = b || v.call(a);try {
+      if (a && a.constructor && !J(a, "constructor") && !J(a.constructor.prototype, "isPrototypeOf")) return !1;
+    } catch (c) {
+      return !1;
+    }return !!a && "[object Object]" === b && "hasOwnProperty" in a;
+  }function I(a, b) {
+    for (var c in a) {
+      if (J(a, c) && !1 === b.call(a, c, a[c], a)) break;
+    }
+  }function wa(a, b) {
+    for (var c = 0; c < a; c++) {
+      b(c);
+    }
+  }function xa(a, b) {
+    I(b, function (c) {
+      a[c] = b[c];
+    });return a;
+  }function ya(a) {
+    ua(a) && (a = m(a));if (ga && z(a)) for (var b = a, c = 0, d; d = b.charAt(c);) {
+      b[c++] = d;
+    }return a;
+  }function O(a) {
+    xa(this, ya(a));
+  }
+  O.prototype.constructor = m;var P = u.abs,
+      za = u.pow,
+      Aa = u.ceil,
+      Q = u.floor,
+      R = u.round,
+      Ca = u.min,
+      S = u.max;function Da(a, b, c) {
+    var d = za(10, P(b || 0));c = c || R;0 > b && (d = 1 / d);return c(a * d) / d;
+  }var Ea = 48,
+      Fa = 57,
+      Ga = 65296,
+      Ha = 65305,
+      Ia = ".",
+      Ja = "",
+      Ka = {},
+      La;function Ma() {
+    return "\t\n\u000b\f\r   ᠎             \u2028\u2029　﻿";
+  }function Na(a, b) {
+    var c = "";for (a = a.toString(); 0 < b;) {
+      if (b & 1 && (c += a), b >>= 1) a += a;
+    }return c;
+  }
+  function Oa(a, b) {
+    var c, d;c = a.replace(La, function (a) {
+      a = Ka[a];a === Ia && (d = !0);return a;
+    });return d ? parseFloat(c) : parseInt(c, b || 10);
+  }function T(a, b, c, d) {
+    d = P(a).toString(d || 10);d = Na("0", b - d.replace(/\.\d+/, "").length) + d;if (c || 0 > a) d = (0 > a ? "-" : "+") + d;return d;
+  }function Pa(a) {
+    if (11 <= a && 13 >= a) return "th";switch (a % 10) {case 1:
+        return "st";case 2:
+        return "nd";case 3:
+        return "rd";default:
+        return "th";}
+  }
+  function Qa(a, b) {
+    function c(a, c) {
+      if (a || -1 < b.indexOf(c)) d += c;
+    }var d = "";b = b || "";c(a.multiline, "m");c(a.ignoreCase, "i");c(a.global, "g");c(a.u, "y");return d;
+  }function Ra(a) {
+    z(a) || (a = s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g, "\\$1");
+  }function U(a, b) {
+    return a["get" + (a._utc ? "UTC" : "") + b]();
+  }function Sa(a, b, c) {
+    return a["set" + (a._utc && "ISOWeek" != b ? "UTC" : "") + b](c);
+  }
+  function Ta(a, b) {
+    var c = typeof a === "undefined" ? "undefined" : _typeof(a),
+        d,
+        e,
+        g,
+        f,
+        h,
+        l,
+        n;if ("string" === c) return a;g = v.call(a);d = va(a, g);e = A(a, g);if (null != a && d || e) {
+      b || (b = []);if (1 < b.length) for (l = b.length; l--;) {
+        if (b[l] === a) return "CYC";
+      }b.push(a);d = a.valueOf() + s(a.constructor);f = e ? a : m.keys(a).sort();l = 0;for (n = f.length; l < n; l++) {
+        h = e ? l : f[l], d += h + Ta(a[h], b);
+      }b.pop();
+    } else d = -Infinity === 1 / a ? "-0" : s(a && a.valueOf ? a.valueOf() : a);return c + g + d;
+  }function Ua(a, b) {
+    return a === b ? 0 !== a || 1 / a === 1 / b : Va(a) && Va(b) ? Ta(a) === Ta(b) : !1;
+  }
+  function Va(a) {
+    var b = v.call(a);return ja.test(b) || va(a, b);
+  }function Wa(a, b, c) {
+    var d,
+        e = a.length,
+        g = b.length,
+        f = !1 !== b[g - 1];if (!(g > (f ? 1 : 2))) return Xa(a, e, b[0], f, c);d = [];L(b, function (b) {
+      if (la(b)) return !1;d.push(Xa(a, e, b, f, c));
+    });return d;
+  }function Xa(a, b, c, d, e) {
+    d && (c %= b, 0 > c && (c = b + c));return e ? a.charAt(c) : a[c];
+  }function Ya(a, b) {
+    K(b, !0, !1, a, function (a, b) {
+      a[b + ("equal" === b ? "s" : "")] = function () {
+        return m[b].apply(null, [this].concat(L(arguments)));
+      };
+    });
+  }na(m);I(w, function (a, b) {
+    na(ba[b]);
+  });var Za, $a;
+  for ($a = 0; 9 >= $a; $a++) {
+    Za = s.fromCharCode($a + Ga), Ja += Za, Ka[Za] = s.fromCharCode($a + Ea);
+  }Ka[","] = "";Ka["．"] = Ia;Ka[Ia] = Ia;La = q("[" + Ja + "．," + Ia + "]", "g");
+  "use strict";H(m, !1, !1, { keys: function keys(a) {
+      var b = [];if (!G(a) && !D(a) && !F(a)) throw new TypeError("Object required");I(a, function (a) {
+        b.push(a);
+      });return b;
+    } });
+  function ab(a, b, c, d) {
+    var e = a.length,
+        g = -1 == d,
+        f = g ? e - 1 : 0;c = isNaN(c) ? f : parseInt(c >> 0);0 > c && (c = e + c);if (!g && 0 > c || g && c >= e) c = f;for (; g && 0 <= c || !g && c < e;) {
+      if (a[c] === b) return c;c += d;
+    }return -1;
+  }function bb(a, b, c, d) {
+    var e = a.length,
+        g = 0,
+        f = M(c);ta(b);if (0 != e || f) f || (c = a[d ? e - 1 : g], g++);else throw new TypeError("Reduce called on empty array with no initial value");for (; g < e;) {
+      f = d ? e - g - 1 : g, f in a && (c = b(c, a[f], f, a)), g++;
+    }return c;
+  }function cb(a) {
+    if (0 === a.length) throw new TypeError("First argument must be defined");
+  }H(p, !1, !1, { isArray: function isArray(a) {
+      return A(a);
+    } });
+  H(p, !0, !1, { every: function every(a, b) {
+      var c = this.length,
+          d = 0;for (cb(arguments); d < c;) {
+        if (d in this && !a.call(b, this[d], d, this)) return !1;d++;
+      }return !0;
+    }, some: function some(a, b) {
+      var c = this.length,
+          d = 0;for (cb(arguments); d < c;) {
+        if (d in this && a.call(b, this[d], d, this)) return !0;d++;
+      }return !1;
+    }, map: function map(a, b) {
+      b = arguments[1];var c = this.length,
+          d = 0,
+          e = Array(c);for (cb(arguments); d < c;) {
+        d in this && (e[d] = a.call(b, this[d], d, this)), d++;
+      }return e;
+    }, filter: function filter(a) {
+      var b = arguments[1],
+          c = this.length,
+          d = 0,
+          e = [];for (cb(arguments); d < c;) {
+        d in this && a.call(b, this[d], d, this) && e.push(this[d]), d++;
+      }return e;
+    }, indexOf: function indexOf(a, b) {
+      return z(this) ? this.indexOf(a, b) : ab(this, a, b, 1);
+    }, lastIndexOf: function lastIndexOf(a, b) {
+      return z(this) ? this.lastIndexOf(a, b) : ab(this, a, b, -1);
+    }, forEach: function forEach(a, b) {
+      var c = this.length,
+          d = 0;for (ta(a); d < c;) {
+        d in this && a.call(b, this[d], d, this), d++;
+      }
+    }, reduce: function reduce(a, b) {
+      return bb(this, a, b);
+    }, reduceRight: function reduceRight(a, b) {
+      return bb(this, a, b, !0);
+    } });
+  H(Function, !0, !1, { bind: function bind(a) {
+      var b = this,
+          c = L(arguments, null, 1),
+          d;if (!F(this)) throw new TypeError("Function.prototype.bind called on a non-function");d = function d() {
+        return b.apply(b.prototype && this instanceof b ? this : a, c.concat(L(arguments)));
+      };d.prototype = this.prototype;return d;
+    } });H(r, !1, !1, { now: function now() {
+      return new r().getTime();
+    } });
+  (function () {
+    var a = Ma().match(/^\s+$/);try {
+      s.prototype.trim.call([1]);
+    } catch (b) {
+      a = !1;
+    }H(s, !0, !a, { trim: function trim() {
+        return this.toString().trimLeft().trimRight();
+      }, trimLeft: function trimLeft() {
+        return this.replace(q("^[" + Ma() + "]+"), "");
+      }, trimRight: function trimRight() {
+        return this.replace(q("[" + Ma() + "]+$"), "");
+      } });
+  })();
+  (function () {
+    var a = new r(r.UTC(1999, 11, 31)),
+        a = a.toISOString && "1999-12-31T00:00:00.000Z" === a.toISOString();K(r, !0, !a, "toISOString,toJSON", function (a, c) {
+      a[c] = function () {
+        return T(this.getUTCFullYear(), 4) + "-" + T(this.getUTCMonth() + 1, 2) + "-" + T(this.getUTCDate(), 2) + "T" + T(this.getUTCHours(), 2) + ":" + T(this.getUTCMinutes(), 2) + ":" + T(this.getUTCSeconds(), 2) + "." + T(this.getUTCMilliseconds(), 3) + "Z";
+      };
+    });
+  })();
+  "use strict";
+  var W,
+      Ib,
+      Jb = "ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),
+      Kb = "({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",
+      Lb = {},
+      Mb,
+      Nb,
+      Ob,
+      Pb = [],
+      Qb = {},
+      X = { yyyy: function yyyy(a) {
+      return U(a, "FullYear");
+    }, yy: function yy(a) {
+      return U(a, "FullYear") % 100;
+    }, ord: function ord(a) {
+      a = U(a, "Date");return a + Pa(a);
+    }, tz: function tz(a) {
+      return a.getUTCOffset();
+    }, isotz: function isotz(a) {
+      return a.getUTCOffset(!0);
+    },
+    Z: function Z(a) {
+      return a.getUTCOffset();
+    }, ZZ: function ZZ(a) {
+      return a.getUTCOffset().replace(/(\d{2})$/, ":$1");
+    } },
+      Rb = [{ name: "year", method: "FullYear", k: !0, b: function b(a) {
+      return 864E5 * (365 + (a ? a.isLeapYear() ? 1 : 0 : 0.25));
+    } }, { name: "month", error: 0.919, method: "Month", k: !0, b: function b(a, _b) {
+      var c = 30.4375,
+          d;a && (d = a.daysInMonth(), _b <= d.days() && (c = d));return 864E5 * c;
+    } }, { name: "week", method: "ISOWeek", b: aa(6048E5) }, { name: "day", error: 0.958, method: "Date", k: !0, b: aa(864E5) }, { name: "hour", method: "Hours", b: aa(36E5) }, { name: "minute",
+    method: "Minutes", b: aa(6E4) }, { name: "second", method: "Seconds", b: aa(1E3) }, { name: "millisecond", method: "Milliseconds", b: aa(1) }],
+      Sb = {};function Tb(a) {
+    xa(this, a);this.g = Pb.concat();
+  }
+  Tb.prototype = { getMonth: function getMonth(a) {
+      return y(a) ? a - 1 : this.months.indexOf(a) % 12;
+    }, getWeekday: function getWeekday(a) {
+      return this.weekdays.indexOf(a) % 7;
+    }, addFormat: function addFormat(a, b, c, d, e) {
+      var g = c || [],
+          f = this,
+          h;a = a.replace(/\s+/g, "[,. ]*");a = a.replace(/\{([^,]+?)\}/g, function (a, b) {
+        var d,
+            e,
+            h,
+            B = b.match(/\?$/);h = b.match(/^(\d+)\??$/);var k = b.match(/(\d)(?:-(\d))?/),
+            E = b.replace(/[^a-z]+$/, "");h ? d = f.tokens[h[1]] : f[E] ? d = f[E] : f[E + "s"] && (d = f[E + "s"], k && (e = [], d.forEach(function (a, b) {
+          var c = b % (f.units ? 8 : d.length);c >= k[1] && c <= (k[2] || k[1]) && e.push(a);
+        }), d = e), d = Ub(d));h ? h = "(?:" + d + ")" : (c || g.push(E), h = "(" + d + ")");B && (h += "?");return h;
+      });b ? (b = Vb(f, e), e = ["t", "[\\s\\u3000]"].concat(f.timeMarker), h = a.match(/\\d\{\d,\d\}\)+\??$/), Wb(f, "(?:" + b + ")[,\\s\\u3000]+?" + a, Jb.concat(g), d), Wb(f, a + "(?:[,\\s]*(?:" + e.join("|") + (h ? "+" : "*") + ")" + b + ")?", g.concat(Jb), d)) : Wb(f, a, g, d);
+    } };
+  function Xb(a, b, c) {
+    var d,
+        e,
+        g = b[0],
+        f = b[1],
+        h = b[2];b = a[c] || a.relative;if (F(b)) return b.call(a, g, f, h, c);e = a.units[8 * (a.plural && 1 < g ? 1 : 0) + f] || a.units[f];a.capitalizeUnit && (e = Yb(e));d = a.modifiers.filter(function (a) {
+      return "sign" == a.name && a.value == (0 < h ? 1 : -1);
+    })[0];return b.replace(/\{(.*?)\}/g, function (a, b) {
+      switch (b) {case "num":
+          return g;case "unit":
+          return e;case "sign":
+          return d.src;}
+    });
+  }function Zb(a, b) {
+    b = b || a.code;return "en" === b || "en-US" === b ? !0 : a.variant;
+  }
+  function $b(a, b) {
+    return b.replace(q(a.num, "g"), function (b) {
+      return ac(a, b) || "";
+    });
+  }function ac(a, b) {
+    var c;return y(b) ? b : b && -1 !== (c = a.numbers.indexOf(b)) ? (c + 1) % 10 : 1;
+  }function Y(a, b) {
+    var c;z(a) || (a = "");c = Sb[a] || Sb[a.slice(0, 2)];if (!1 === b && !c) throw new TypeError("Invalid locale.");return c || Ib;
+  }
+  function bc(a, b) {
+    function c(a) {
+      var b = h[a];z(b) ? h[a] = b.split(",") : b || (h[a] = []);
+    }function d(a, b) {
+      a = a.split("+").map(function (a) {
+        return a.replace(/(.+):(.+)$/, function (a, b, c) {
+          return c.split("|").map(function (a) {
+            return b + a;
+          }).join("|");
+        });
+      }).join("|");a.split("|").forEach(b);
+    }function e(a, b, c) {
+      var e = [];h[a].forEach(function (a, f) {
+        b && (a += "+" + a.slice(0, 3));d(a, function (a, b) {
+          e[b * c + f] = a.toLowerCase();
+        });
+      });h[a] = e;
+    }function g(a, b, c) {
+      a = "\\d{" + a + "," + b + "}";c && (a += "|(?:" + Ub(h.numbers) + ")+");return a;
+    }function f(a, b) {
+      h[a] = h[a] || b;
+    }var h, l;h = new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l = !h.monthSuffix;e("months", l, 12);e("weekdays", l, 7);e("units", !1, 8);e("numbers", !1, 10);f("code", a);f("date", g(1, 2, h.digitDate));f("year", "'\\d{2}|" + g(4, 4));f("num", function () {
+      var a = ["-?\\d+"].concat(h.articles);h.numbers && (a = a.concat(h.numbers));return Ub(a);
+    }());(function () {
+      var a = [];h.i = {};h.modifiers.push({ name: "day", src: "yesterday", value: -1 });
+      h.modifiers.push({ name: "day", src: "today", value: 0 });h.modifiers.push({ name: "day", src: "tomorrow", value: 1 });h.modifiers.forEach(function (b) {
+        var c = b.name;d(b.src, function (d) {
+          var e = h[c];h.i[d] = b;a.push({ name: c, src: d, value: b.value });h[c] = e ? e + "|" + d : d;
+        });
+      });h.day += "|" + Ub(h.weekdays);h.modifiers = a;
+    })();h.monthSuffix && (h.month = g(1, 2), h.months = "1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function (a) {
+      return a + h.monthSuffix;
+    }));h.full_month = g(1, 2) + "|" + Ub(h.months);0 < h.timeSuffixes.length && h.addFormat(Vb(h), !1, Jb);
+    h.addFormat("{day}", !0);h.addFormat("{month}" + (h.monthSuffix || ""));h.addFormat("{year}" + (h.yearSuffix || ""));h.timeParse.forEach(function (a) {
+      h.addFormat(a, !0);
+    });h.dateParse.forEach(function (a) {
+      h.addFormat(a);
+    });return Sb[a] = h;
+  }function Wb(a, b, c, d) {
+    a.g.unshift({ r: d, locale: a, q: q("^" + b + "$", "i"), to: c });
+  }function Yb(a) {
+    return a.slice(0, 1).toUpperCase() + a.slice(1);
+  }function Ub(a) {
+    return a.filter(function (a) {
+      return !!a;
+    }).join("|");
+  }function cc() {
+    var a = r.SugarNewDate;return a ? a() : new r();
+  }
+  function dc(a, b) {
+    var c;if (G(a[0])) return a;if (y(a[0]) && !y(a[1])) return [a[0]];if (z(a[0]) && b) return [ec(a[0]), a[1]];c = {};Nb.forEach(function (b, e) {
+      c[b.name] = a[e];
+    });return [c];
+  }function ec(a) {
+    var b,
+        c = {};if (a = a.match(/^(\d+)?\s?(\w+?)s?$/i)) N(b) && (b = parseInt(a[1]) || 1), c[a[2].toLowerCase()] = b;return c;
+  }function fc(a, b, c) {
+    var d;N(c) && (c = Ob.length);for (b = b || 0; b < c && (d = Ob[b], !1 !== a(d.name, d, b)); b++) {}
+  }
+  function gc(a, b) {
+    var c = {},
+        d,
+        e;b.forEach(function (b, f) {
+      d = a[f + 1];N(d) || "" === d || ("year" === b && (c.t = d.replace(/'/, "")), e = parseFloat(d.replace(/'/, "").replace(/,/, ".")), c[b] = isNaN(e) ? d.toLowerCase() : e);
+    });return c;
+  }function hc(a) {
+    a = a.trim().replace(/^just (?=now)|\.+$/i, "");return ic(a);
+  }
+  function ic(a) {
+    return a.replace(Mb, function (a, c, d) {
+      var e = 0,
+          g = 1,
+          f,
+          h;if (c) return a;d.split("").reverse().forEach(function (a) {
+        a = Lb[a];var b = 9 < a;b ? (f && (e += g), g *= a / (h || 1), h = a) : (!1 === f && (g *= 10), e += g * a);f = b;
+      });f && (e += g);return e;
+    });
+  }
+  function jc(a, b, c, d) {
+    function e(a) {
+      vb.push(a);
+    }function g() {
+      vb.forEach(function (a) {
+        a.call();
+      });
+    }function f() {
+      var a = n.getWeekday();n.setWeekday(7 * (k.num - 1) + (a > Ba ? Ba + 7 : Ba));
+    }function h() {
+      var a = B.i[k.edge];fc(function (a) {
+        if (M(k[a])) return E = a, !1;
+      }, 4);if ("year" === E) k.e = "month";else if ("month" === E || "week" === E) k.e = "day";n[(0 > a.value ? "endOf" : "beginningOf") + Yb(E)]();-2 === a.value && n.reset();
+    }function l() {
+      var a;fc(function (b, c, d) {
+        "day" === b && (b = "date");if (M(k[b])) {
+          if (d >= wb) return n.setTime(NaN), !1;a = a || {};a[b] = k[b];
+          delete k[b];
+        }
+      });a && e(function () {
+        n.set(a, !0);
+      });
+    }var n, x, ha, vb, B, k, E, wb, Ba, ra, ca;n = cc();vb = [];n.utc(d);C(a) ? n.utc(a.isUTC()).setTime(a.getTime()) : y(a) ? n.setTime(a) : G(a) ? (n.set(a, !0), k = a) : z(a) && (ha = Y(b), a = hc(a), ha && I(ha.o ? [ha.o].concat(ha.g) : ha.g, function (c, d) {
+      var g = a.match(d.q);if (g) {
+        B = d.locale;k = gc(g, d.to);B.o = d;k.utc && n.utc();if (k.timestamp) return k = k.timestamp, !1;d.r && !z(k.month) && (z(k.date) || Zb(ha, b)) && (ca = k.month, k.month = k.date, k.date = ca);k.year && 2 === k.t.length && (k.year = 100 * R(U(cc(), "FullYear") / 100) - 100 * R(k.year / 100) + k.year);k.month && (k.month = B.getMonth(k.month), k.shift && !k.unit && (k.unit = B.units[7]));k.weekday && k.date ? delete k.weekday : k.weekday && (k.weekday = B.getWeekday(k.weekday), k.shift && !k.unit && (k.unit = B.units[5]));k.day && (ca = B.i[k.day]) ? (k.day = ca.value, n.reset(), x = !0) : k.day && -1 < (Ba = B.getWeekday(k.day)) && (delete k.day, k.num && k.month ? (e(f), k.day = 1) : k.weekday = Ba);k.date && !y(k.date) && (k.date = $b(B, k.date));k.ampm && k.ampm === B.ampm[1] && 12 > k.hour ? k.hour += 12 : k.ampm === B.ampm[0] && 12 === k.hour && (k.hour = 0);if ("offset_hours" in k || "offset_minutes" in k) n.utc(), k.offset_minutes = k.offset_minutes || 0, k.offset_minutes += 60 * k.offset_hours, "-" === k.offset_sign && (k.offset_minutes *= -1), k.minute -= k.offset_minutes;k.unit && (x = !0, ra = ac(B, k.num), wb = B.units.indexOf(k.unit) % 8, E = W.units[wb], l(), k.shift && (ra *= (ca = B.i[k.shift]) ? ca.value : 0), k.sign && (ca = B.i[k.sign]) && (ra *= ca.value), M(k.weekday) && (n.set({ weekday: k.weekday }, !0), delete k.weekday), k[E] = (k[E] || 0) + ra);k.edge && e(h);"-" === k.year_sign && (k.year *= -1);fc(function (a, b, c) {
+          b = k[a];var d = b % 1;d && (k[Ob[c - 1].name] = R(d * ("second" === a ? 1E3 : 60)), k[a] = Q(b));
+        }, 1, 4);return !1;
+      }
+    }), k ? x ? n.advance(k) : (n._utc && n.reset(), kc(n, k, !0, !1, c)) : ("now" !== a && (n = new r(a)), d && n.addMinutes(-n.getTimezoneOffset())), g(), n.utc(!1));return { c: n, set: k };
+  }function lc(a) {
+    var b,
+        c = P(a),
+        d = c,
+        e = 0;fc(function (a, f, h) {
+      b = Q(Da(c / f.b(), 1));1 <= b && (d = b, e = h);
+    }, 1);return [d, e, a];
+  }
+  function mc(a) {
+    var b = lc(a.millisecondsFromNow());if (6 === b[1] || 5 === b[1] && 4 === b[0] && a.daysFromNow() >= cc().daysInMonth()) b[0] = P(a.monthsFromNow()), b[1] = 6;return b;
+  }function nc(a, b, c) {
+    function d(a, c) {
+      var d = U(a, "Month");return Y(c).months[d + 12 * b];
+    }Z(a, d, c);Z(Yb(a), d, c, 1);
+  }function Z(a, b, c, d) {
+    X[a] = function (a, g) {
+      var f = b(a, g);c && (f = f.slice(0, c));d && (f = f.slice(0, d).toUpperCase() + f.slice(d));return f;
+    };
+  }
+  function oc(a, b, c) {
+    X[a] = b;X[a + a] = function (a, c) {
+      return T(b(a, c), 2);
+    };c && (X[a + a + a] = function (a, c) {
+      return T(b(a, c), 3);
+    }, X[a + a + a + a] = function (a, c) {
+      return T(b(a, c), 4);
+    });
+  }function pc(a) {
+    var b = a.match(/(\{\w+\})|[^{}]+/g);Qb[a] = b.map(function (a) {
+      a.replace(/\{(\w+)\}/, function (b, e) {
+        a = X[e] || e;return e;
+      });return a;
+    });
+  }
+  function qc(a, b, c, d) {
+    var e;if (!a.isValid()) return "Invalid Date";Date[b] ? b = Date[b] : F(b) && (e = mc(a), b = b.apply(a, e.concat(Y(d))));if (!b && c) return e = e || mc(a), 0 === e[1] && (e[1] = 1, e[0] = 1), a = Y(d), Xb(a, e, 0 < e[2] ? "future" : "past");b = b || "long";if ("short" === b || "long" === b || "full" === b) b = Y(d)[b];Qb[b] || pc(b);var g, f;e = "";b = Qb[b];g = 0;for (c = b.length; g < c; g++) {
+      f = b[g], e += F(f) ? f(a, d) : f;
+    }return e;
+  }
+  function rc(a, b, c, d, e) {
+    var g,
+        f,
+        h,
+        l = 0,
+        n = 0,
+        x = 0;g = jc(b, c, null, e);0 < d && (n = x = d, f = !0);if (!g.c.isValid()) return !1;if (g.set && g.set.e) {
+      Rb.forEach(function (b) {
+        b.name === g.set.e && (l = b.b(g.c, a - g.c) - 1);
+      });b = Yb(g.set.e);if (g.set.edge || g.set.shift) g.c["beginningOf" + b]();"month" === g.set.e && (h = g.c.clone()["endOf" + b]().getTime());!f && g.set.sign && "millisecond" != g.set.e && (n = 50, x = -50);
+    }f = a.getTime();b = g.c.getTime();h = sc(a, b, h || b + l);return f >= b - n && f <= h + x;
+  }
+  function sc(a, b, c) {
+    b = new r(b);a = new r(c).utc(a.isUTC());23 !== U(a, "Hours") && (b = b.getTimezoneOffset(), a = a.getTimezoneOffset(), b !== a && (c += (a - b).minutes()));return c;
+  }
+  function kc(a, b, c, d, e) {
+    function g(a) {
+      return M(b[a]) ? b[a] : b[a + "s"];
+    }function f(a) {
+      return M(g(a));
+    }var h;if (y(b) && d) b = { milliseconds: b };else if (y(b)) return a.setTime(b), a;M(b.date) && (b.day = b.date);fc(function (d, e, g) {
+      var l = "day" === d;if (f(d) || l && f("weekday")) return b.e = d, h = +g, !1;!c || "week" === d || l && f("week") || Sa(a, e.method, l ? 1 : 0);
+    });Rb.forEach(function (c) {
+      var e = c.name;c = c.method;var h;h = g(e);N(h) || (d ? ("week" === e && (h = (b.day || 0) + 7 * h, c = "Date"), h = h * d + U(a, c)) : "month" === e && f("day") && Sa(a, "Date", 15), Sa(a, c, h), d && "month" === e && (e = h, 0 > e && (e = e % 12 + 12), e % 12 != U(a, "Month") && Sa(a, "Date", 0)));
+    });d || f("day") || !f("weekday") || a.setWeekday(g("weekday"));var l;a: {
+      switch (e) {case -1:
+          l = a > cc();break a;case 1:
+          l = a < cc();break a;}l = void 0;
+    }l && fc(function (b, c) {
+      if ((c.k || "week" === b && f("weekday")) && !(f(b) || "day" === b && f("weekday"))) return a[c.j](e), !1;
+    }, h + 1);return a;
+  }
+  function Vb(a, b) {
+    var c = Kb,
+        d = { h: 0, m: 1, s: 2 },
+        e;a = a || W;return c.replace(/{([a-z])}/g, function (c, f) {
+      var h = [],
+          l = "h" === f,
+          n = l && !b;if ("t" === f) return a.ampm.join("|");l && h.push(":");(e = a.timeSuffixes[d[f]]) && h.push(e + "\\s*");return 0 === h.length ? "" : "(?:" + h.join("|") + ")" + (n ? "" : "?");
+    });
+  }function tc(a, b, c) {
+    var d, e;y(a[1]) ? d = dc(a)[0] : (d = a[0], e = a[1]);return jc(d, e, b, c).c;
+  }
+  H(r, !1, !0, { create: function create() {
+      return tc(arguments);
+    }, past: function past() {
+      return tc(arguments, -1);
+    }, future: function future() {
+      return tc(arguments, 1);
+    }, addLocale: function addLocale(a, b) {
+      return bc(a, b);
+    }, setLocale: function setLocale(a) {
+      var b = Y(a, !1);Ib = b;a && a != b.code && (b.code = a);return b;
+    }, getLocale: function getLocale(a) {
+      return a ? Y(a, !1) : Ib;
+    }, addFormat: function addFormat(a, b, c) {
+      Wb(Y(c), a, b);
+    } });
+  H(r, !0, !0, { set: function set() {
+      var a = dc(arguments);return kc(this, a[0], a[1]);
+    }, setWeekday: function setWeekday(a) {
+      if (!N(a)) return Sa(this, "Date", U(this, "Date") + a - U(this, "Day"));
+    }, setISOWeek: function setISOWeek(a) {
+      var b = U(this, "Day") || 7;if (!N(a)) return this.set({ month: 0, date: 4 }), this.set({ weekday: 1 }), 1 < a && this.addWeeks(a - 1), 1 !== b && this.advance({ days: b - 1 }), this.getTime();
+    }, getISOWeek: function getISOWeek() {
+      var a;a = this.clone();var b = U(a, "Day") || 7;a.addDays(4 - b).reset();return 1 + Q(a.daysSince(a.clone().beginningOfYear()) / 7);
+    }, beginningOfISOWeek: function beginningOfISOWeek() {
+      var a = this.getDay();0 === a ? a = -6 : 1 !== a && (a = 1);this.setWeekday(a);return this.reset();
+    }, endOfISOWeek: function endOfISOWeek() {
+      0 !== this.getDay() && this.setWeekday(7);return this.endOfDay();
+    }, getUTCOffset: function getUTCOffset(a) {
+      var b = this._utc ? 0 : this.getTimezoneOffset(),
+          c = !0 === a ? ":" : "";return !b && a ? "Z" : T(Q(-b / 60), 2, !0) + c + T(P(b % 60), 2);
+    }, utc: function utc(a) {
+      oa(this, "_utc", !0 === a || 0 === arguments.length);return this;
+    }, isUTC: function isUTC() {
+      return !!this._utc || 0 === this.getTimezoneOffset();
+    }, advance: function advance() {
+      var a = dc(arguments, !0);return kc(this, a[0], a[1], 1);
+    }, rewind: function rewind() {
+      var a = dc(arguments, !0);return kc(this, a[0], a[1], -1);
+    }, isValid: function isValid() {
+      return !isNaN(this.getTime());
+    }, isAfter: function isAfter(a, b) {
+      return this.getTime() > r.create(a).getTime() - (b || 0);
+    }, isBefore: function isBefore(a, b) {
+      return this.getTime() < r.create(a).getTime() + (b || 0);
+    }, isBetween: function isBetween(a, b, c) {
+      var d = this.getTime();a = r.create(a).getTime();var e = r.create(b).getTime();b = Ca(a, e);a = S(a, e);c = c || 0;return b - c < d && a + c > d;
+    }, isLeapYear: function isLeapYear() {
+      var a = U(this, "FullYear");return 0 === a % 4 && 0 !== a % 100 || 0 === a % 400;
+    },
+    daysInMonth: function daysInMonth() {
+      return 32 - U(new r(U(this, "FullYear"), U(this, "Month"), 32), "Date");
+    }, format: function format(a, b) {
+      return qc(this, a, !1, b);
+    }, relative: function relative(a, b) {
+      z(a) && (b = a, a = null);return qc(this, a, !0, b);
+    }, is: function is(a, b, c) {
+      var d, e;if (this.isValid()) {
+        if (z(a)) switch (a = a.trim().toLowerCase(), e = this.clone().utc(c), !0) {case "future" === a:
+            return this.getTime() > cc().getTime();case "past" === a:
+            return this.getTime() < cc().getTime();case "weekday" === a:
+            return 0 < U(e, "Day") && 6 > U(e, "Day");case "weekend" === a:
+            return 0 === U(e, "Day") || 6 === U(e, "Day");case -1 < (d = W.weekdays.indexOf(a) % 7):
+            return U(e, "Day") === d;case -1 < (d = W.months.indexOf(a) % 12):
+            return U(e, "Month") === d;}return rc(this, a, null, b, c);
+      }
+    }, reset: function reset(a) {
+      var b = {},
+          c;a = a || "hours";"date" === a && (a = "days");c = Rb.some(function (b) {
+        return a === b.name || a === b.name + "s";
+      });b[a] = a.match(/^days?/) ? 1 : 0;return c ? this.set(b, !0) : this;
+    }, clone: function clone() {
+      var a = new r(this.getTime());a.utc(!!this._utc);return a;
+    } });
+  H(r, !0, !0, { iso: function iso() {
+      return this.toISOString();
+    }, getWeekday: r.prototype.getDay, getUTCWeekday: r.prototype.getUTCDay });function uc(a, b) {
+    function c() {
+      return R(this * b);
+    }function d() {
+      return tc(arguments)[a.j](this);
+    }function e() {
+      return tc(arguments)[a.j](-this);
+    }var g = a.name,
+        f = {};f[g] = c;f[g + "s"] = c;f[g + "Before"] = e;f[g + "sBefore"] = e;f[g + "Ago"] = e;f[g + "sAgo"] = e;f[g + "After"] = d;f[g + "sAfter"] = d;f[g + "FromNow"] = d;f[g + "sFromNow"] = d;t.extend(f);
+  }H(t, !0, !0, { duration: function duration(a) {
+      a = Y(a);return Xb(a, lc(this), "duration");
+    } });
+  W = Ib = r.addLocale("en", { plural: !0, timeMarker: "at", ampm: "am,pm", months: "January,February,March,April,May,June,July,August,September,October,November,December", weekdays: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", units: "millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s", numbers: "one,two,three,four,five,six,seven,eight,nine,ten", articles: "a,an,the", tokens: "the,st|nd|rd|th,of", "short": "{Month} {d}, {yyyy}", "long": "{Month} {d}, {yyyy} {h}:{mm}{tt}", full: "{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
+    past: "{num} {unit} {sign}", future: "{num} {unit} {sign}", duration: "{num} {unit}", modifiers: [{ name: "sign", src: "ago|before", value: -1 }, { name: "sign", src: "from now|after|from|in|later", value: 1 }, { name: "edge", src: "last day", value: -2 }, { name: "edge", src: "end", value: -1 }, { name: "edge", src: "first day|beginning", value: 1 }, { name: "shift", src: "last", value: -1 }, { name: "shift", src: "the|this", value: 0 }, { name: "shift", src: "next", value: 1 }], dateParse: ["{month} {year}", "{shift} {unit=5-7}", "{0?} {date}{1}", "{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
+    timeParse: "{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";") });Ob = Rb.concat().reverse();Nb = Rb.concat();Nb.splice(2, 1);
+  K(r, !0, !0, Rb, function (a, b, c) {
+    function d(a) {
+      a /= f;var c = a % 1,
+          d = b.error || 0.999;c && P(c % 1) > d && (a = R(a));return 0 > a ? Aa(a) : Q(a);
+    }var e = b.name,
+        g = Yb(e),
+        f = b.b(),
+        h,
+        l;b.j = "add" + g + "s";h = function h(a, b) {
+      return d(this.getTime() - r.create(a, b).getTime());
+    };l = function l(a, b) {
+      return d(r.create(a, b).getTime() - this.getTime());
+    };a[e + "sAgo"] = l;a[e + "sUntil"] = l;a[e + "sSince"] = h;a[e + "sFromNow"] = h;a[b.j] = function (a, b) {
+      var c = {};c[e] = a;return this.advance(c, b);
+    };uc(b, f);3 > c && ["Last", "This", "Next"].forEach(function (b) {
+      a["is" + b + g] = function () {
+        return rc(this, b + " " + e, "en");
+      };
+    });4 > c && (a["beginningOf" + g] = function () {
+      var a = {};switch (e) {case "year":
+          a.year = U(this, "FullYear");break;case "month":
+          a.month = U(this, "Month");break;case "day":
+          a.day = U(this, "Date");break;case "week":
+          a.weekday = 0;}return this.set(a, !0);
+    }, a["endOf" + g] = function () {
+      var a = { hours: 23, minutes: 59, seconds: 59, milliseconds: 999 };switch (e) {case "year":
+          a.month = 11;a.day = 31;break;case "month":
+          a.day = this.daysInMonth();break;case "week":
+          a.weekday = 6;}return this.set(a, !0);
+    });
+  });
+  W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?", !0, ["year_sign", "year", "month", "date"], !1, !0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?", !0, ["date", "month", "year"], !0);W.addFormat("{full_month}[-.](\\d{4,4})", !1, ["month", "year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/", !1, ["timestamp"]);W.addFormat(Vb(W), !1, Jb);Pb = W.g.slice(0, 7).reverse();W.g = W.g.slice(7).concat(Pb);oc("f", function (a) {
+    return U(a, "Milliseconds");
+  }, !0);
+  oc("s", function (a) {
+    return U(a, "Seconds");
+  });oc("m", function (a) {
+    return U(a, "Minutes");
+  });oc("h", function (a) {
+    return U(a, "Hours") % 12 || 12;
+  });oc("H", function (a) {
+    return U(a, "Hours");
+  });oc("d", function (a) {
+    return U(a, "Date");
+  });oc("M", function (a) {
+    return U(a, "Month") + 1;
+  });(function () {
+    function a(a, c) {
+      var d = U(a, "Hours");return Y(c).ampm[Q(d / 12)] || "";
+    }Z("t", a, 1);Z("tt", a);Z("T", a, 1, 1);Z("TT", a, null, 2);
+  })();
+  /* istanbul ignore next */
+  (function () {
+    function a(a, c) {
+      var d = U(a, "Day");return Y(c).weekdays[d];
+    }Z("dow", a, 3);Z("Dow", a, 3, 1);Z("weekday", a);Z("Weekday", a, null, 1);
+  })();nc("mon", 0, 3);nc("month", 0);nc("month2", 1);nc("month3", 2);X.ms = X.f;X.milliseconds = X.f;X.seconds = X.s;X.minutes = X.m;X.hours = X.h;X["24hr"] = X.H;X["12hr"] = X.h;X.date = X.d;X.day = X.d;X.year = X.yyyy;K(r, !0, !0, "short,long,full", function (a, b) {
+    a[b] = function (a) {
+      return qc(this, b, !1, a);
+    };
+  });
+  "〇一二三四五六七八九十百千万".split("").forEach(function (a, b) {
+    9 < b && (b = za(10, b - 9));Lb[a] = b;
+  });xa(Lb, Ka);Mb = q("([期週周])?([〇一二三四五六七八九十百千万" + Ja + "]+)(?!昨)", "g");
+  /* istanbul ignore next */
+  (function () {
+    var a = W.weekdays.slice(0, 7),
+        b = W.months.slice(0, 12);K(r, !0, !0, "today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b), function (a, b) {
+      a["is" + Yb(b)] = function (a) {
+        return this.is(b, 0, a);
+      };
+    });
+  })();r.utc || (r.utc = { create: function create() {
+      return tc(arguments, 0, !0);
+    }, past: function past() {
+      return tc(arguments, -1, !0);
+    }, future: function future() {
+      return tc(arguments, 1, !0);
+    } });
+  H(r, !1, !0, { RFC1123: "{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}", RFC1036: "{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}", ISO8601_DATE: "{yyyy}-{MM}-{dd}", ISO8601_DATETIME: "{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}" });
+})();
\ No newline at end of file
diff --git a/packages/touch/dist/util/interfacer.js b/packages/touch/dist/util/interfacer.js
new file mode 100755
index 0000000..4bf2ddc
--- /dev/null
+++ b/packages/touch/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  var self = this;
+  var stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {
+    exec: function exec() {}
+  };
+
+  var logger = {
+    log: function log(out) {
+      stdout += out + '\n';
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = result === undefined ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
\ No newline at end of file
diff --git a/packages/touch/package.json b/packages/touch/package.json
new file mode 100644
index 0000000..1773ff1
--- /dev/null
+++ b/packages/touch/package.json
@@ -0,0 +1,51 @@
+{
+  "name": "cash-touch",
+  "version": "0.1.0",
+  "description": "Cross-platform implementation of the Unix 'touch' command.",
+  "main": "./dist/commands/touch.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dthree/cash.git"
+  },
+  "keywords": [
+    "cash",
+    "terminal",
+    "emulator",
+    "cygwin",
+    "cli",
+    "windows",
+    "linux",
+    "unix",
+    "posix",
+    "bash",
+    "tty",
+    "util",
+    "vorpal",
+    "vorpal.js"
+  ],
+  "author": "dthree",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/dthree/cash/issues"
+  },
+  "homepage": "https://github.com/dthree/cash#readme",
+  "devDependencies": {},
+  "bin": {
+    "touch": "./bin/touch.js"
+  },
+  "dependencies": {
+    "lodash": "^4.0.0",
+    "fs-extra": "^0.23.1",
+    "vorpal-autocomplete-fs": "0.0.3",
+    "vorpal": "^1.9.5"
+  },
+  "engines": {
+    "node": ">= 0.11.16",
+    "iojs": ">= 1.0.0"
+  },
+  "files": [
+    "dist",
+    "bin"
+  ]
+}
diff --git a/src/commands/alias.js b/src/commands/alias.js
new file mode 100755
index 0000000..6a32d2c
--- /dev/null
+++ b/src/commands/alias.js
@@ -0,0 +1,113 @@
+'use strict';
+
+const _ = require('lodash');
+
+const interfacer = require('./../util/interfacer');
+
+const alias = {
+
+  exec(args, options) {
+    args = args || [];
+    options = options || {};
+    const vorpal = options.vorpal;
+
+    if (!vorpal) {
+      throw new Error('Alias is not programatically supported.');
+    }
+
+    vorpal._aliases = vorpal._aliases || [];
+
+    if (args.length < 1) {
+      options.p = true;
+    }
+
+    if (_.isString(args)) {
+      args = [args];
+    }
+
+    // Parse incoming args. Accept either:
+    // alias foo=bar, or
+    // alias foo 'bar and so on'.
+    let key = args.join(' ');
+    let value;
+    if (String(key).indexOf('=') > -1) {
+      const parts = String(key).trim().split('=');
+      key = parts[0];
+      value = parts[1] || value;
+    } else {
+      const parts = String(key).trim().split(' ');
+      key = parts.shift();
+      value = parts.join(' ');
+    }
+
+    // Remove wrapped quotes from value.
+    if (value !== undefined) {
+      value = String(value).replace(/^[\"|\']|[\"|\']$/g, '');
+    }
+
+    // Pull list of aliases
+    let all;
+    try {
+      all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      all = [];
+      vorpal.localStorage.removeItem('aliases');
+    }
+
+    if (options.p) {
+      for (let i = 0; i < all.length; ++i) {
+        const item = vorpal.localStorage.getItem(`alias|${all[i]}`);
+        if (item !== undefined && item !== null) {
+          this.log(`alias ${all[i]}='${item}'`);
+        }
+      }
+    } else {
+      if (value) {
+        vorpal.localStorage.setItem(`alias|${key}`, value);
+        _.remove(all, function (val) {
+          return val === key;
+        });
+        all.push(key);
+      } else {
+        const item = vorpal.localStorage.getItem(`alias|${key}`);
+        if (item !== undefined && item !== null) {
+          this.log(`alias ${key}='${item}'`);
+        } else {
+          this.log(`-cash: alias: ${key}: not found`);
+        }
+      }
+
+      const aliases = {};
+      for (let i = 0; i < all.length; ++i) {
+        const item = vorpal.localStorage.getItem(`alias|${all[i]}`);
+        if (item !== undefined && item !== null) {
+          aliases[all[i]] = item;
+        }
+      }
+      vorpal._aliases = aliases;
+    }
+
+    vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return alias;
+  }
+  vorpal.api.alias = alias;
+  vorpal
+    .command('alias [name...]')
+    .option('-p', 'print all defined aliases in a reusable format')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      args.options.vorpal = vorpal;
+      return interfacer.call(this, {
+        command: alias,
+        args: args.name,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/boilerplate.js b/src/commands/boilerplate.js
new file mode 100755
index 0000000..df111ba
--- /dev/null
+++ b/src/commands/boilerplate.js
@@ -0,0 +1,101 @@
+'use strict';
+
+const interfacer = require('./../util/interfacer');
+
+/**
+ * This is a boilerplate for implementing a new command.
+ * Delete all of these comments / instructions before finishing.
+ */
+
+/**
+ * 0. Replace all instances of `cmdName` with
+ *    the exact name of the command being implemented.
+ */
+
+const cmdName = {
+
+  /**
+   * The cmdName.exec method is exposed by Cash
+   * as the only public interfacer to your command.
+   */
+
+  exec(args, options) {
+    options = options || {};
+
+    /**
+     * 1. Validate arg input to include every
+     *    possible form of input, such as:
+     *
+     *    a. as a string:
+     *       cash.foo('bar and so on', {option: true});
+     *
+     *    b. as an array:
+     *       cash.foo(['bar', 'and', 'so', 'on'], {option: true});
+     *
+     *    c. as interpeted through Vorpal:
+     *       cash('foo bar and so on --option');
+     */
+
+    /**
+     * 2. For errors, use `this.log` to print the
+     *    error message to the user, and only return
+     *    the error code (1, 2, etc.)
+     *
+     *    if (args.length < 1) {
+     *      this.log('foo: cannot bar: requires at least one file name');
+     *      return 1;
+     *    }
+     */
+
+    /**
+     * 3. For all other stdout to the user, use `this.log`.
+     *    For large jobs that should stream logging a
+     *    bit at a time, use multiple `this.log` statements
+     *    and cash will handle the heavy lifting of piping
+     *    and returning the final assembled output to the
+     *    user in the case of programmatically executed
+     *    commands.
+     */
+
+    /**
+     * 4. When complete with no errors, return 0;
+     *
+     *    return 0;
+     */
+  }
+};
+
+module.exports = function (vorpal) {
+  /**
+   * When do a raw execution of the command
+   * without options, Vorpal is not used. In this
+   * case, the raw command is returned.
+   */
+  if (vorpal === undefined) {
+    return cmdName;
+  }
+  vorpal.api.cmdName = cmdName;
+  /**
+   * Registers the command in Vorpal.
+   * Command strings, options and their
+   * descriptions should exactly emulate
+   * existing commands.
+   */
+  vorpal
+    .command('cmdName [files...]')
+    .option('-o, --option', 'option description')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      /**
+       * The interfacer method does a
+       * lot of heavy lifting on interfacing with
+       * the command properly.
+       */
+      return interfacer.call(this, {
+        command: cmdName,
+        args: args.files, // only pass in what you need from Vorpal
+        options: args.options, // split the options into their own arg
+        callback
+      });
+    });
+};
diff --git a/src/commands/cat.js b/src/commands/cat.js
new file mode 100755
index 0000000..ae20562
--- /dev/null
+++ b/src/commands/cat.js
@@ -0,0 +1,133 @@
+'use strict';
+
+const _ = require('lodash');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const fetch = require('./../util/fetch');
+const interfacer = require('./../util/interfacer');
+const lpad = require('./../util/lpad');
+const strip = require('./../util/stripAnsi');
+
+const cat = {
+
+  exec(args, options) {
+    const self = this;
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    // -A handler
+    if (options.showall) {
+      options.shownonprinting = true;
+      options.showends = true;
+      options.showtabs = true;
+    }
+
+    // -e handler
+    if (options.e) {
+      options.shownonprinting = true;
+      options.showends = true;
+    }
+
+    // -t handler
+    if (options.t) {
+      options.shownonprinting = true;
+      options.showtabs = true;
+    }
+
+    let stdout = '';
+    try {
+      const stdin = fetch(args.files, args.stdin, {
+        onDirectory(name) {
+          return `cat: ${name}: Is a directory`;
+        },
+        onInvalidFile(name) {
+          return `cat: ${name}: No such file or directory`;
+        }
+      });
+      let ctr = 0;
+      for (let i = 0; i < stdin.length; ++i) {
+        // If -s, squeeze double blank lines to a
+        // single line.
+        if (options.squeezeblank) {
+          stdin[i] = stdin[i].replace(/\n\n\s*\n/g, '\n\n');
+        }
+        if (options.showtabs) {
+          stdin[i] = stdin[i].replace(/\t/g, '^I');
+        }
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        stdin[i] = stdin[i].replace(/\s$/, '');
+        const parts = String(stdin[i]).split('\n');
+        for (let j = 0; j < parts.length; ++j) {
+          const blank = ((strip(parts[j])).trim() === '');
+          // If -b, number every non-blank line
+          // If -n, number every line
+          const numbered = ((!blank && options.numbernonblank) || (options.number && !options.numbernonblank));
+          if (numbered) {
+            ctr++;
+          }
+          const numStr = (numbered) ?
+            `${lpad(String(ctr), 6, ' ')}  ` :
+            '';
+          // If -E, append a $ to each line end.
+          const dollarStr = (options.showends) ? '$' : '';
+          const line =
+            numStr +
+            parts[j] +
+            dollarStr;
+          self.log(line);
+          stdout += `${line}\n`;
+        }
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return 1;
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cat;
+  }
+  vorpal.api.cat = cat;
+  vorpal
+    .command('cat [files...]')
+    .option('-A, --show-all', 'equivalent to -vET')
+    .option('-b, --number-nonblank', 'number nonempty output lines, overrides -n')
+    .option('-e', 'equivalent to -vE')
+    .option('-E, --show-ends', 'display $ at end of each line')
+    .option('-n, --number', 'number all output lines')
+    .option('-s, --squeeze-blank', 'suppress repeated empty output lines')
+    .option('-t', 'equivalent to -vT')
+    .option('-T, --show-tabs', 'display TAB characters as ^I')
+    .option('-v, --show-nonprinting', 'use ^ and M- notation, except for LFD and TAB') // this doesn't work yet...
+    .autocomplete(fsAutocomplete())
+    .action(function (args, cb) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: cat,
+        args,
+        options: args.options,
+        callback: cb
+      });
+    });
+};
diff --git a/src/commands/cd.js b/src/commands/cd.js
new file mode 100755
index 0000000..27b5086
--- /dev/null
+++ b/src/commands/cd.js
@@ -0,0 +1,60 @@
+'use strict';
+
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+const delimiter = require('./../delimiter');
+
+const interfacer = require('./../util/interfacer');
+
+const cd = {
+
+  exec(dir, options) {
+    const self = this;
+    const vpl = options.vorpal;
+    options = options || {};
+
+    dir = (!dir) ? delimiter.getHomeDir() : dir;
+    try {
+      process.chdir(dir);
+      if (vpl) {
+        delimiter.refresh(vpl);
+      }
+      return 0;
+    } catch (e) {
+      return cd.error.call(self, e, dir);
+    }
+  },
+
+  error(e, dir) {
+    let status;
+    let stdout;
+    if (e.code === 'ENOENT' && e.syscall === 'uv_chdir') {
+      status = 1;
+      stdout = `-bash: cd: ${dir}: No such file or directory`;
+    } else {
+      status = 2;
+      stdout = e.stack;
+    }
+    this.log(stdout);
+    return status;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cd;
+  }
+  vorpal.api.cd = cd;
+  vorpal
+    .command('cd [dir]')
+    .autocomplete(fsAutocomplete({directory: true}))
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      args.options.vorpal = vorpal;
+      return interfacer.call(this, {
+        command: cd,
+        args: args.dir,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/cp.js b/src/commands/cp.js
new file mode 100755
index 0000000..515d623
--- /dev/null
+++ b/src/commands/cp.js
@@ -0,0 +1,213 @@
+'use strict';
+
+const _ = require('lodash');
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+const path = require('path');
+const os = require('os');
+
+const expand = require('./../util/expand');
+const interfacer = require('./../util/interfacer');
+
+const cp = {
+
+  exec(args, options) {
+    const self = this;
+    options = options || {};
+
+    args = (args === undefined) ? [] : args;
+    args = (_.isArray(args)) ? args : args.split(' ');
+    args = _.filter(args, arg => String(arg).trim() !== '');
+
+    options.noclobber = (options.force === true) ? false : options.noclobber;
+    options.recursive = (options.R === true) ? true : options.recursive;
+
+    if (args.length < 1) {
+      this.log('cp: missing file operand\nTry \'cp --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log(`cp: missing destination file operand after ${args[0]}\nTry 'cp --help' for more information.`);
+      return 1;
+    }
+
+    args = expand(args);
+
+    const dest = args.pop();
+    let sources = args;
+
+    const exists = fs.existsSync(dest);
+    const stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log(`cp: target ${dest} is not a directory`);
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.recursive) {
+      sources.forEach(function (src, i) {
+        if (src[src.length - 1] === '/') {
+          sources[i] += '*';
+        } else if (fs.statSync(src).isDirectory() && !exists) {
+          sources[i] += '/*';
+        }
+      });
+      try {
+        fs.mkdirSync(dest, parseInt('0777', 8));
+      } catch (e) {
+        // like Unix's cp, keep going even if we can't create dest dir
+      }
+    }
+
+    sources = expand(sources);
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log(`cp: cannot stat ${src}: No such file or directory`);
+        return;
+      }
+
+      if (fs.statSync(src).isDirectory()) {
+        if (!options.recursive) {
+          self.log(`cp: omitting directory ${src}`);
+        } else {
+          // 'cp /a/source dest' should create 'source' in 'dest'
+          const newDest = path.join(dest, path.basename(src));
+          const checkDir = fs.statSync(src);
+          try {
+            fs.mkdirSync(newDest, checkDir.mode);
+          } catch (e) {
+            /* istanbul ignore if */
+            if (e.code !== 'EEXIST') {
+              throw new Error();
+            }
+          }
+          cpdirSyncRecursive.call(self, src, newDest, options);
+        }
+        return;
+      }
+
+      // If here, src is a file
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      let iDest = dest;
+      if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
+        iDest = path.normalize(`${dest}/${path.basename(src)}`);
+      }
+
+      if (fs.existsSync(iDest) && options.no_force) {
+        return;
+      }
+
+      copyFileSync.call(self, src, iDest);
+    });
+  }
+};
+
+function cpdirSyncRecursive(sourceDir, destDir, options) {
+  const self = this;
+  /* istanbul ignore if */
+  if (!options) {
+    options = {};
+  }
+  const checkDir = fs.statSync(sourceDir);
+  try {
+    fs.mkdirSync(destDir, checkDir.mode);
+  } catch (e) {
+    /* istanbul ignore if */
+    if (e.code !== 'EEXIST') {
+      throw e;
+    }
+  }
+  const files = fs.readdirSync(sourceDir);
+  for (let i = 0; i < files.length; i++) {
+    const srcFile = `${sourceDir}/${files[i]}`;
+    const destFile = `${destDir}/${files[i]}`;
+    const srcFileStat = fs.lstatSync(srcFile);
+    if (srcFileStat.isDirectory()) {
+      // recursion this thing right on back.
+      cpdirSyncRecursive.call(self, srcFile, destFile, options);
+    } else if (srcFileStat.isSymbolicLink()) {
+      const symlinkFull = fs.readlinkSync(srcFile);
+      fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null);
+      // At this point, we've hit a file actually worth copying... so copy it on over.
+    } else if (fs.existsSync(destFile) && options.noclobber) {
+      // be silent
+    } else {
+      copyFileSync.call(self, srcFile, destFile);
+    }
+  }
+}
+
+function copyFileSync(src, dest) {
+  /* istanbul ignore if */
+  if (!fs.existsSync(src)) {
+    this.log(`cp: cannot stat ${src}: No such file or directory`);
+    return;
+  }
+
+  const BUF_LENGTH = 64 * 1024;
+  const buf = new Buffer(BUF_LENGTH);
+  let bytesRead = BUF_LENGTH;
+  let pos = 0;
+  let fdr = null;
+  let fdw = null;
+
+  try {
+    fdr = fs.openSync(src, 'r');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log(`cp: cannot open ${src}: ${e.code}`);
+    /* istanbul ignore next */
+    return;
+  }
+
+  try {
+    fdw = fs.openSync(dest, 'w');
+  } catch (e) {
+    /* istanbul ignore next */
+    this.log(`cp: cannot write to destination file ${dest}: ${e.code}`);
+    /* istanbul ignore next */
+    return;
+  }
+
+  while (bytesRead === BUF_LENGTH) {
+    bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+    fs.writeSync(fdw, buf, 0, bytesRead);
+    pos += bytesRead;
+  }
+
+  fs.closeSync(fdr);
+  fs.closeSync(fdw);
+  fs.chmodSync(dest, fs.statSync(src).mode);
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return cp;
+  }
+  vorpal.api.cp = cp;
+  vorpal
+    .command('cp [args...]')
+    .option('-f, --force', 'do not prompt before overwriting')
+    .option('-n, --no-clobber', 'do not overwrite an existing file')
+    .option('-r, --recursive', 'copy directories recursively')
+    .option('-R', 'copy directories recursively')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: cp,
+        args: args.args,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/echo.js b/src/commands/echo.js
new file mode 100755
index 0000000..5300a1f
--- /dev/null
+++ b/src/commands/echo.js
@@ -0,0 +1,84 @@
+'use strict';
+
+const _ = require('lodash');
+
+const interfacer = require('./../util/interfacer');
+
+const echo = {
+
+  exec(arg, options) {
+    const self = this;
+    options = options || {};
+
+    try {
+      let text = arg || '';
+      text = !_.isArray(text) ? [text] : text;
+      let result = text.join(' ');
+      let out = '';
+      if (options.e && !options.E) {
+        for (let i = 0; i < result.length; ++i) {
+          const nxt = result[i] + (result[i + 1] || '');
+          if (nxt === '\\b') {
+            out = out.slice(0, out.length - 1);
+            i++;
+          } else if (nxt === '\\c') {
+            break;
+          } else if (nxt === '\\n') {
+            out += '\n';
+            i++;
+          } else if (nxt === '\\r') {
+            out += '\r';
+            i++;
+          } else if (nxt === '\\t') {
+            out += '     ';
+            i++;
+          } else if (nxt === '\\\\') {
+            out += '\\';
+            i += 2;
+          } else {
+            out += result[i];
+          }
+        }
+        result = out;
+      }
+
+      // Bug: If nothing is passed, ensure we keep
+      // a blank line. Vorpal is designed to just
+      // eat blank lines, so we have a problem.
+      result = result === ('') ? '' : result;
+
+      this.log(result);
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      return echo.error.call(self, e);
+    }
+  },
+
+  error(e) {
+    /* istanbul ignore next */
+    this.log(e.stack);
+    /* istanbul ignore next */
+    return 2;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return echo;
+  }
+  vorpal.api.echo = echo;
+  vorpal
+    .command('echo [arg...]')
+    .option('-e', 'enable interpretation of the following backslash escapes')
+    .option('-E', 'explicitly suppress interpretation of backslash escapes')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: echo,
+        args: args.arg,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/grep.js b/src/commands/grep.js
new file mode 100755
index 0000000..b6cf138
--- /dev/null
+++ b/src/commands/grep.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-grep');
diff --git a/src/commands/kill.js b/src/commands/kill.js
new file mode 100755
index 0000000..47c90e4
--- /dev/null
+++ b/src/commands/kill.js
@@ -0,0 +1,103 @@
+'use strict';
+
+const _ = require('lodash');
+const fkill = require('fkill');
+const os = require('os');
+
+const interfacer = require('./../util/interfacer');
+
+const usage = `kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]`;
+const windows = (os.platform().indexOf('win') > -1);
+const signals = {
+  SIGKILL: 9,
+  SIGTERM: 15,
+  KILL: 9,
+  TERM: 15,
+  9: 'KILL',
+  15: 'TERM'
+};
+
+const kill = {
+
+  exec(args, options) {
+    options = options || {};
+
+    let procs = args;
+    procs = (procs === undefined) ? [] : procs;
+    procs = (typeof procs === 'string') ? String(procs).split(' ') : procs;
+    procs = _.filter(procs, arg => String(arg).trim() !== '');
+
+    function log(str) {
+      if (options.vorpal) {
+        options.vorpal.log(str);
+      } else {
+        /* istanbul ignore next */
+        console.log(str);
+      }
+    }
+
+    if (options.l !== undefined) {
+      if (options.l === true) {
+        this.log(` 9) SIGKILL   15) SIGTERM`);
+        return 0;
+      }
+      if (signals[options.l]) {
+        this.log(signals[options.l]);
+        return 0;
+      }
+      this.log(`-cash: kill: ${options.l}: invalid signal specification`);
+      return 0;
+    }
+
+    if (procs.length < 1) {
+      this.log(usage);
+      return 0;
+    }
+
+    const forced = (options['9'] === true) ||
+      (options.n === 9) ||
+      (String(options.s).toLowerCase() === 'sigkill') ||
+      (String(options.s).toLowerCase() === 'kill');
+    const opts = {force: forced};
+
+    for (let i = 0; i < procs.length; ++i) {
+      let proc = procs[i];
+      proc = (!isNaN(proc)) ? parseFloat(proc) : proc;
+      proc = (windows && isNaN(proc) && proc.indexOf('.') === -1) ?
+        `${proc}.exe` :
+        proc;
+      fkill(proc, opts).then(function () {
+        // .. chill
+      }).catch(function (err) {
+        if (String(err.message).indexOf('failed') > -1) {
+          log(`-cash: kill: (${proc}) - No such process`);
+        }
+      });
+    }
+
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return kill;
+  }
+  vorpal.api.kill = kill;
+  vorpal
+    .command('kill [process...]')
+    .option('-9', 'sigkill')
+    .option('-s [sig]', 'sig is a signal name')
+    .option('-n [sig]', 'sig is a signal number')
+    .option('-l [sigspec]', 'list the signal names')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      args.options.vorpal = vorpal;
+      return interfacer.call(this, {
+        command: kill,
+        args: args.process,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/less.js b/src/commands/less.js
new file mode 100755
index 0000000..3e8c9ab
--- /dev/null
+++ b/src/commands/less.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-less');
diff --git a/src/commands/ls.js b/src/commands/ls.js
new file mode 100755
index 0000000..09b359c
--- /dev/null
+++ b/src/commands/ls.js
@@ -0,0 +1,376 @@
+'use strict';
+
+const _ = require('lodash');
+const chalk = require('chalk');
+const filesize = require('filesize');
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+const os = require('os');
+
+const colorFile = require('./../util/colorFile');
+const columnify = require('./../util/columnify');
+const dateConverter = require('./../util/converter.date');
+const fileFromPath = require('./../util/fileFromPath');
+const interfacer = require('./../util/interfacer');
+const pad = require('./../util/pad');
+const lpad = require('./../util/lpad');
+const permissionsConverter = require('./../util/converter.permissions');
+const strip = require('./../util/stripAnsi');
+const walkDir = require('./../util/walkDir');
+const walkDirRecursive = require('./../util/walkDirRecursive');
+
+const pads = {pad, lpad};
+
+const ls = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec(paths, options) {
+    const self = this;
+    paths = (!_.isArray(paths) && _.isObject(paths)) ? paths.paths : paths;
+    paths = paths || ['.'];
+    paths = (_.isArray(paths)) ? paths : [paths];
+    options = options || {};
+    try {
+      let results = [];
+      for (let i = 0; i < paths.length; ++i) {
+        if (options.recursive) {
+          const result = ls.execDirRecursive(paths[i], options);
+          results = results.concat(result);
+        } else {
+          const result = ls.execDir(paths[i], options);
+          results.push(result);
+        }
+      }
+      const stdout = ls.formatAll(results, options);
+      if (strip(stdout).trim() !== '') {
+        self.log(String(stdout).replace(/\\/g, '/'));
+      }
+      return 0;
+    } catch (e) {
+      /* istanbul ignore next */
+      return ls.error.call(self, e);
+    }
+  },
+
+  /**
+   * Returns ls stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error(e) {
+    /* istanbul ignore next */
+    let status;
+    /* istanbul ignore next */
+    let stdout;
+    /* istanbul ignore next */
+    if (e.code === 'ENOENT' && e.syscall === 'scandir') {
+      status = 1;
+      stdout = `ls: cannot access: No such file or directory`;
+    } else {
+      /* istanbul ignore next */
+      status = 2;
+      /* istanbul ignore next */
+      stdout = e.stack;
+    }
+    /* istanbul ignore next */
+    this.log(stdout);
+    /* istanbul ignore next */
+    return status;
+  },
+
+  /**
+   * Recursively executes `execDir`.
+   * For use with `ls -R`.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDirRecursive(path, options) {
+    const self = this;
+    const results = [];
+    walkDirRecursive(path, pth => {
+      const result = self.execDir(pth, options);
+      results.push(result);
+    });
+    return results;
+  },
+
+  /**
+   * Executes `ls` functionality
+   * for a given directory.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @return {String} results
+   * @api private
+   */
+
+  execDir(path, options) {
+    const files = [];
+    let rawFiles = [];
+    let totalSize = 0;
+
+    function pushFile(file, data) {
+      rawFiles.push({
+        file,
+        data
+      });
+    }
+
+    // Add in implied current and parent dirs.
+    pushFile('.', fs.statSync('.'));
+    pushFile('..', fs.statSync('..'));
+
+    // Walk the passed in directory,
+    // pushing the results into `rawFiles`.
+    walkDir(path, pushFile);
+
+    // Sort alphabetically be default,
+    // unless -U is specified, in which case
+    // we don't sort.
+    if (!options.U) {
+      rawFiles = rawFiles.sort(function (a, b) {
+        // Sort by size.
+        if (options.S) {
+          // Hack for windows - a directory lising
+          // in linux says the size is 4096, and Windows
+          // it's 0, leading to inconsistent sorts based
+          // on size, and failing tests.
+          const win = (os.platform() === 'win32');
+          a.data.size = (win && a.data.isDirectory() && a.data.size === 0) ? 4096 : a.data.size;
+          b.data.size = (win && b.data.isDirectory() && b.data.size === 0) ? 4096 : b.data.size;
+          return (a.data.size > b.data.size) ? -1 : (a.data.size < b.data.size) ? 1 : 0;
+        }
+        if (options.t) {
+          // Sort by date modified.
+          return ((a.data.mtime < b.data.mtime) ? 1 :
+            (b.data.mtime < a.data.mtime) ? -1 :
+            0);
+        }
+        // Sort alphabetically - default.
+        const aFileName = fileFromPath(a.file)
+          .trim()
+          .toLowerCase()
+          .replace(/\W/g, '');
+        const bFileName = fileFromPath(b.file)
+          .trim()
+          .toLowerCase()
+          .replace(/\W/g, '');
+        return (aFileName > bFileName) ? 1 : (aFileName < bFileName) ? -1 : 0;
+      });
+    }
+
+    // Reverse whatever sort the user specified.
+    if (options.reverse) {
+      rawFiles.reverse();
+    }
+
+    for (let i = 0; i < rawFiles.length; ++i) {
+      const file = rawFiles[i].file;
+      const data = rawFiles[i].data;
+      const fileShort = fileFromPath(file);
+      const dotted = (fileShort && fileShort.charAt(0) === '.');
+      const implied = (fileShort === '..' || fileShort === '.');
+      const type = (data.isDirectory()) ? 'd' : '-';
+      const permissions = permissionsConverter.modeToRWX(data.mode);
+      const hardLinks = data.nlink;
+      const size = (options.humanreadable) ? filesize(data.size, {unix: true}) : data.size;
+      const modified = dateConverter.unix(data.mtime);
+      const owner = data.uid;
+      const group = data.gid;
+      const inode = data.ino;
+
+      totalSize += data.size;
+
+      let fileName = fileShort;
+
+      // If --classify, add '/' to end of folders.
+      fileName = (options.classify && data.isDirectory()) ?
+        `${fileName}/` :
+        fileName;
+
+      // If getting --directory, give full path.
+      fileName = (options.directory && file === '.') ? path : fileName;
+
+      // Color the files based on $LS_COLORS
+      fileName = (data.isFile()) ? colorFile(fileName) : fileName;
+
+      // If not already colored and is executable,
+      // make it green
+      const colored = (strip(fileName) !== fileName);
+      if (String(permissions).indexOf('x') > -1 && !colored && data.isFile()) {
+        fileName = chalk.green(fileName);
+      }
+
+      // If --quote-name, wrap in double quotes;
+      fileName = (options.quotename) ? `"${fileName}"` : fileName;
+
+      // Make directories cyan.
+      fileName = (data.isDirectory()) ? chalk.cyan(fileName) : fileName;
+
+      const include = (() => {
+        const directory = options.directory;
+        const all = options.all;
+        const almostAll = options.almostall;
+        let result = false;
+        if (directory && file !== '.') {
+          result = false;
+        } else if (!dotted) {
+          result = true;
+        } else if (all) {
+          result = true;
+        } else if (!implied && almostAll) {
+          result = true;
+        } else if (directory && file === '.') {
+          result = true;
+        }
+        return result;
+      })();
+
+      const details = [type + permissions, hardLinks, owner, group, size, modified, fileName];
+
+      if (options.inode) {
+        details.unshift(inode);
+      }
+
+      const result =
+        (options.l && !options.x) ? details :
+        fileName;
+
+      if (include) {
+        files.push(result);
+      }
+    }
+
+    let result;
+
+    // If we have the detail view, draw out
+    // all of the details of each file.
+    // Otherwise, just throw the file names
+    // into columns.
+    if (_.isArray(files[0])) {
+      const longest = {};
+      for (let i = 0; i < files.length; ++i) {
+        for (let j = 0; j < files[i].length; ++j) {
+          const len = String(files[i][j]).length;
+          longest[j] = longest[j] || 0;
+          longest[j] = (len > longest[j]) ? len : longest[j];
+        }
+      }
+
+      const newFiles = [];
+      for (let i = 0; i < files.length; ++i) {
+        let glob = '';
+        for (let j = 0; j < files[i].length; ++j) {
+          const padFn = (j === files[i].length - 1) ? 'pad' : 'lpad';
+          if (j === files[i].length - 1) {
+            glob += String(files[i][j]);
+          } else {
+            glob += `${pads[padFn](String(files[i][j]), longest[j], ' ')} `;
+          }
+        }
+        newFiles.push(String(glob));
+      }
+      result = newFiles.join('\n');
+    } else if (options['1']) {
+      result = files.join('\n');
+    } else {
+      const opt = {};
+      if (options.width) {
+        opt.width = options.width;
+      }
+      result = columnify(files, opt);
+    }
+
+    return ({
+      path,
+      size: (options.humanreadable) ? filesize(totalSize, {unix: true}) : totalSize,
+      results: result
+    });
+  },
+
+  /**
+   * Concatenates the results of multiple
+   * `execDir` functions into their proper
+   * form based on options provided.
+   *
+   * @param {String} results
+   * @param {Object} options
+   * @return {String} stdout
+   * @api private
+   */
+
+  formatAll(results, options) {
+    let stdout = '';
+    if (results.length > 1) {
+      for (let i = 0; i < results.length; ++i) {
+        stdout += `${results[i].path}:\n`;
+        if (options.l) {
+          stdout += `total ${results[i].size}\n`;
+        }
+        stdout += results[i].results;
+        if (i !== results.length - 1) {
+          stdout += '\n\n';
+        }
+      }
+    } else if (results.length === 1) {
+      if (options.l && !options.x) {
+        stdout += `total ${results[0].size}\n`;
+      }
+      stdout += results[0].results;
+    }
+    return stdout;
+  }
+};
+
+/**
+ * Expose as a Vorpal extension.
+ */
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return ls;
+  }
+  vorpal.api.ls = ls;
+  vorpal
+    .command('ls [paths...]')
+    .option('-a, --all', 'do not ignore entries starting with .')
+    .option('-A, --almost-all', 'do not list implied . and ..')
+    .option('-d, --directory', 'list directory entries instead of contents, and do not dereference symbolic links')
+    .option('-F, --classify', 'append indicator (one of */=>@|) to entries')
+    .option('-h, --human-readable', 'with -l, print sizes in human readable format (e.g., 1K 234M 2G)')
+    .option('-i, --inode', 'print the index number of each file')
+    .option('-l', 'use a long listing format')
+    .option('-Q, --quote-name', 'enclose entry names in double quotes')
+    .option('-r, --reverse', 'reverse order while sorting')
+    .option('-R, --recursive', 'list subdirectories recursively')
+    .option('-S', 'sort by file size')
+    .option('-t', 'sort by modification time, newest first')
+    .option('-U', 'do not sort; list entries in directory order')
+    .option('-w, --width [COLS]', 'assume screen width instead of current value')
+    .option('-x', 'list entries by lines instead of columns')
+    .option('-1', 'list one file per line')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, cb) {
+      return interfacer.call(this, {
+        command: ls,
+        args: args.paths,
+        options: args.options,
+        callback: cb
+      });
+    });
+};
diff --git a/src/commands/mkdir.js b/src/commands/mkdir.js
new file mode 100755
index 0000000..21d623f
--- /dev/null
+++ b/src/commands/mkdir.js
@@ -0,0 +1,90 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const interfacer = require('./../util/interfacer');
+
+const mkdir = {
+
+  exec(args, options) {
+    const self = this;
+    let dirs = args || [];
+    options = options || {};
+
+    if (typeof dirs === 'string') {
+      dirs = dirs.split(' ');
+    }
+
+    dirs = dirs.filter(str => String(str).trim() !== '');
+
+    if (dirs.length < 1) {
+      this.log('mkdir: missing operand\nTry \'mkdir --help\' for more information.');
+    }
+
+    dirs.forEach(function (dir) {
+      if (fs.existsSync(dir)) {
+        if (!options.parents) {
+          self.log(`mkdir: cannot create directory ${dir}: File exists`);
+        }
+        return;
+      }
+
+      // Base dir does not exist, and no -p option given
+      const baseDir = path.dirname(dir);
+      if (!fs.existsSync(baseDir) && !options.parents) {
+        self.log(`mkdir: cannot create directory ${dir}: No such file or directory`);
+        return;
+      }
+
+      if (options.parents) {
+        mkdirSyncRecursive.call(self, dir, options);
+      } else {
+        fs.mkdirSync(dir, parseInt('0777', 8));
+        if (options.verbose) {
+          self.log(`mkdir: created directory ${dir}`);
+        }
+      }
+    });
+    return 0;
+  }
+};
+
+function mkdirSyncRecursive(dir, options) {
+  const baseDir = path.dirname(dir);
+  if (fs.existsSync(baseDir)) {
+    fs.mkdirSync(dir, parseInt('0777', 8));
+    if (options.verbose) {
+      this.log(`mkdir: created directory ${dir}`);
+    }
+    return;
+  }
+  mkdirSyncRecursive.call(this, baseDir, options);
+  fs.mkdirSync(dir, parseInt('0777', 8));
+  if (options.verbose) {
+    this.log(`mkdir: created directory ${dir}`);
+  }
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mkdir;
+  }
+  vorpal.api.mkdir = mkdir;
+  vorpal
+    .command('mkdir [directory...]')
+    .option('-p, --parents', 'no error if existing, make parent directories as needed')
+    .option('-v, --verbose', 'print a message for each created directory')
+    .autocomplete(fsAutocomplete({directory: true}))
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      args.options.vorpal = vorpal;
+      return interfacer.call(this, {
+        command: mkdir,
+        args: args.directory,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/mv.js b/src/commands/mv.js
new file mode 100755
index 0000000..95e5708
--- /dev/null
+++ b/src/commands/mv.js
@@ -0,0 +1,108 @@
+'use strict';
+
+const _ = require('lodash');
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+const path = require('path');
+
+const expand = require('./../util/expand');
+const interfacer = require('./../util/interfacer');
+
+const mv = {
+
+  exec(args, options) {
+    const self = this;
+    options = options || {};
+
+    args = (args === undefined) ? [] : args;
+    args = (_.isArray(args)) ? args : args.split(' ');
+    args = _.filter(args, arg => String(arg).trim() !== '');
+
+    options.noclobber = (options.force === true) ? false : options.noclobber;
+
+    if (args.length < 1) {
+      this.log('mv: missing file operand\nTry \'mv --help\' for more information.');
+      return 1;
+    }
+
+    if (args.length === 1) {
+      this.log(`mv: missing destination file operand after ${args[0]}\nTry 'mv --help' for more information.`);
+      return 1;
+    }
+
+    args = expand(args);
+
+    const dest = args.pop();
+    let sources = args;
+
+    const exists = fs.existsSync(dest);
+    const stats = exists && fs.statSync(dest);
+
+    // Dest is not existing dir, but multiple sources given
+    if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+      this.log(`mv: target ${dest} is not a directory`);
+      return 1;
+    }
+
+    // Dest is an existing file, but no -f given
+    if (exists && stats.isFile() && options.noclobber) {
+      // just dont do anything
+      return 0;
+    }
+
+    if (options.striptrailingslashes) {
+      sources = sources.map(src => String(src).replace(/\/$/g, ''));
+    }
+
+    sources.forEach(function (src) {
+      if (!fs.existsSync(src)) {
+        self.log(`mv: cannot stat ${src}: No such file or directory`);
+        return;
+      }
+
+      // When copying to '/path/dir', iDest = '/path/dir/file1'
+      let iDest = dest;
+      if (exists && stats.isDirectory()) {
+        iDest = path.normalize(`${dest}/${path.basename(src)}`);
+      }
+
+      // If the file exists and we're not clobbering, skip.
+      if (fs.existsSync(iDest) && options.noclobber) {
+        return;
+      }
+
+      if (path.resolve(src) === path.dirname(path.resolve(iDest))) {
+        self.log(`mv: ${src} and ${iDest} are the same file`);
+        return;
+      }
+
+      fs.renameSync(src, iDest);
+      if (options.verbose === true) {
+        self.log(String(`${src} -> ${iDest}`).replace(/\\/g, '/'));
+      }
+    });
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return mv;
+  }
+  vorpal.api.mv = mv;
+  vorpal
+    .command('mv [args...]')
+    .option('-f, --force', 'do not prompt before overwriting')
+    .option('-n, --no-clobber', 'do not overwrite an existing file')
+    .option('--striptrailingslashes', 'remove any trailing slashes from each source') // vorpal bug, need to add dashes between words
+    .option('-v, --verbose', 'explain what is being done')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: mv,
+        args: args.args,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/pwd.js b/src/commands/pwd.js
new file mode 100755
index 0000000..0cba8ce
--- /dev/null
+++ b/src/commands/pwd.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const path = require('path');
+
+const interfacer = require('./../util/interfacer');
+
+const pwd = {
+  exec() {
+    this.log(path.resolve(process.cwd()).replace(/\\/g, '/'));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return pwd;
+  }
+  vorpal.api.pwd = pwd;
+  vorpal
+    .command('pwd [files...]')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: pwd,
+        args: args.files,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/rm.js b/src/commands/rm.js
new file mode 100755
index 0000000..56f4888
--- /dev/null
+++ b/src/commands/rm.js
@@ -0,0 +1,179 @@
+'use strict';
+
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const expand = require('./../util/expand');
+const interfacer = require('./../util/interfacer');
+const unlinkSync = require('./../util/unlinkSync');
+
+const rm = {
+
+  exec(args, options) {
+    const self = this;
+    options = options || {};
+    options.recursive = (options.R) ?
+      options.R :
+      options.recursive;
+
+    let files = args;
+    files = (files === undefined) ? [] : files;
+    files = (typeof files === 'string') ? [files] : files;
+
+    files = expand(files);
+
+    files.forEach(function (file) {
+      if (!fs.existsSync(file)) {
+        // Path does not exist, no force flag given
+        if (!options.force) {
+          self.log(`rm: cannot remove ${file}: No such file or directory`);
+          return 2;
+        }
+        /* istanbul ignore next */
+        return 0;
+      }
+
+      const stats = fs.lstatSync(file);
+      if (stats.isFile() || stats.isSymbolicLink()) {
+        if (options.force) {
+          unlinkSync(file);
+          return 0;
+        }
+
+        if (isWriteable(file)) {
+          unlinkSync(file);
+        } else {
+          /* istanbul ignore next */
+          self.log(`rm: cannot remove ${file}: permission denied`);
+          /* istanbul ignore next */
+          return 2;
+        }
+        return 0;
+      }
+
+      // Path is an existing directory, but no -r flag given
+      if (stats.isDirectory() && !options.recursive) {
+        self.log(`rm: cannot remove: path is a directory`);
+        return 2;
+      }
+
+      // Recursively remove existing directory
+      if (stats.isDirectory() && options.recursive) {
+        rmdirSyncRecursive.call(self, file, options.force, options.dir);
+      }
+    });
+  }
+};
+
+function rmdirSyncRecursive(dir, force, removeEmptyDir) {
+  const self = this;
+  let files;
+  files = fs.readdirSync(dir);
+
+  // Loop through and delete everything in the sub-tree after checking it
+  for (let i = 0; i < files.length; i++) {
+    const file = `${dir}/${files[i]}`;
+    const currFile = fs.lstatSync(file);
+
+    if (currFile.isDirectory()) { // Recursive function back to the beginning
+      rmdirSyncRecursive(file, force, removeEmptyDir);
+    } else if (currFile.isSymbolicLink()) {
+      // Unlink symlinks
+      /* istanbul ignore next */
+      if (force || isWriteable(file)) {
+        try {
+          unlinkSync(file);
+        } catch (e) {
+          self.log(`rm: cannot remove ${file}: code ${e.code}`);
+          return 2;
+        }
+      }
+    } else if (force || isWriteable(file)) {
+      // Assume it's a file.
+      try {
+        unlinkSync(file);
+      } catch (e) {
+        /* istanbul ignore next */
+        self.log(`rm: cannot remove ${file}: code ${e.code}`);
+        /* istanbul ignore next */
+        return 2;
+      }
+    }
+  }
+
+  // Now that we know everything in the sub-tree has been deleted,
+  // we can delete the main directory.
+  let result;
+  try {
+    // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+    const start = Date.now();
+    while (true) {
+      try {
+        result = fs.rmdirSync(dir);
+        /* istanbul ignore next */
+        if (fs.existsSync(dir)) {
+          throw new Error('EAGAIN');
+        }
+        break;
+      } catch (er) {
+        // In addition to error codes, also check if the directory still exists and loop again if true
+        /* istanbul ignore next */
+        if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+          if (Date.now() - start > 1000) {
+            throw er;
+          }
+        /* istanbul ignore next */
+        } else if (er.code === 'ENOENT') {
+          // Directory did not exist, deletion was successful
+          break;
+        /* istanbul ignore next */
+        } else {
+          throw er;
+        }
+      }
+    }
+  } catch (e) {
+    /* istanbul ignore next */
+    self.log(`rm: cannot remove directory ${dir}: code ${e.code}`);
+    /* istanbul ignore next */
+    return 2;
+  }
+  return result;
+}
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow.
+function isWriteable(file) {
+  let writePermission = true;
+  try {
+    const __fd = fs.openSync(file, 'a');
+    fs.closeSync(__fd);
+  } catch (e) {
+    /* istanbul ignore next */
+    writePermission = false;
+  }
+
+  return writePermission;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return rm;
+  }
+  vorpal.api.rm = rm;
+  vorpal
+    .command('rm [files...]')
+    .option('-f, --force', 'ignore nonexistent files and arguments, never prompt')
+    .option('-r, --recursive', 'remove directories and their contents recursively')
+    .option('-R', 'remove directories and their contents recursively')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: rm,
+        args: args.files,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/sort.js b/src/commands/sort.js
new file mode 100755
index 0000000..6f22447
--- /dev/null
+++ b/src/commands/sort.js
@@ -0,0 +1,279 @@
+'use strict';
+
+const _ = require('lodash');
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const fetch = require('./../util/fetch');
+const interfacer = require('./../util/interfacer');
+const strip = require('./../util/stripAnsi');
+
+const sort = {
+
+  counter: 0,
+
+  stdin: '',
+
+  exec(args, options) {
+    const self = this;
+
+    // Hack to handle multiple calls
+    // due to fragmented stdin, such as
+    // by piping. In essence, we're waiting
+    // 100 milliseconds for all of the
+    // requests to come in, and then running
+    // sort. Only applies when sort is called
+    // through a piped command.
+    /* istanbul ignore next */
+    if (args && args.stdin && options.bypass !== true) {
+      sort.counter++;
+      sort.stdin += `${args.stdin}\n`;
+      if (sort.counter === 1) {
+        setTimeout(function () {
+          sort.counter = 0;
+          args.stdin = sort.stdin;
+          sort.stdin = '';
+          options.bypass = true;
+          sort.exec.call(self, args, options);
+        }, 100);
+      }
+      return;
+    }
+    sort.counter = 0;
+    sort.stdin = '';
+
+    // Input normalization
+    if (args === undefined) {
+      args = {
+        files: []
+      };
+    } else if (_.isString(args)) {
+      args = {
+        files: [args]
+      };
+    } else if (_.isArray(args)) {
+      args = {
+        files: args
+      };
+    }
+
+    options = options || {};
+
+    function log(stdout) {
+      if (options.output) {
+        if (options.output === true) {
+          self.log(`sort: option '--output' requires an argument\nTry 'sort --help' for more information.`);
+          return 0;
+        }
+        try {
+          fs.writeFileSync(options.output, stdout);
+          return 0;
+        } catch (e) {
+          if (e.code === 'ENOENT') {
+            self.log(`sort: open failed: ${options.output}: No such file or directory`);
+          } else {
+            /* istanbul ignore next */
+            self.log(`sort: open failed: ${options.output}: ${e.code}`);
+          }
+          return 2;
+        }
+      } else {
+        self.log(stdout);
+      }
+    }
+
+    try {
+      const stdin = fetch(args.files, args.stdin, {
+        onDirectory(name) {
+          /* istanbul ignore next */
+          return `sort: read failed: ${name}: Is a directory`;
+        },
+        onInvalidFile(name) {
+          /* istanbul ignore next */
+          return `sort: cannot read: ${name}: No such file or directory`;
+        }
+      });
+
+      let combined = '';
+      for (let i = 0; i < stdin.length; ++i) {
+        // Get rid of trailing line break because
+        // node logging does it anyway.
+        combined += stdin[i];
+      }
+
+      combined = combined.replace(/\s$/, '');
+      let parts = String(combined).split('\n');
+
+      if (options.check) {
+        // Check if the thing was already sorted.
+        const original = String(combined).split('\n');
+        let disorder;
+        for (let i = 0; i < original.length; ++i) {
+          const a = original[i];
+          const b = original[i + 1];
+          if (a && b) {
+            if (!isNaN(a) && !isNaN(b) && parseFloat(a) > parseFloat(b)) {
+              /* istanbul ignore next */
+              disorder = true;
+            } else if (a > b) {
+              disorder = true;
+            }
+            if (disorder) {
+              // To do: right now, I don't say the file
+              // name of the bad sorted item - I have to
+              // figure this out as I join all the files
+              // together beforehand and lose track.
+              disorder = `sort: -:${(i + 2)}: disorder: ${b}`;
+              break;
+            }
+          }
+        }
+        if (disorder) {
+          log(disorder);
+          return;
+        }
+      }
+
+      parts = parts.sort(function (a, b) {
+        const aAlpha = strip(a).replace(/\W+/g, '');
+        const bAlpha = strip(b).replace(/\W+/g, '');
+        const aNumeric = strip(a).replace(/\D/g, '');
+        const bNumeric = strip(b).replace(/\D/g, '');
+        if (options.humannumericsort) {
+          const aHuman = parseHumanReadableNumbers(strip(a));
+          const bHuman = parseHumanReadableNumbers(strip(b));
+          if (aHuman.group < bHuman.group) {
+            return -1;
+          } else if (aHuman.group > bHuman.group) {
+            return 1;
+          } else if (aHuman.num < bHuman.num) {
+            return -1;
+          } else if (aHuman.num > bHuman.num) {
+            return 1;
+          }
+          return aAlpha.localeCompare(bAlpha);
+        } else if (options.monthsort) {
+          const aMonth = parseMonths(strip(a));
+          const bMonth = parseMonths(strip(b));
+          let result = aMonth - bMonth;
+          if (aMonth === bMonth) {
+            result = aAlpha.localeCompare(bAlpha);
+          }
+          return result;
+        } else if (options.numericsort) {
+          let result = aNumeric - bNumeric;
+          result = (result === 0) ? aAlpha.localeCompare(bAlpha) : result;
+          return result;
+        }
+        return aAlpha.localeCompare(bAlpha);
+      });
+
+      if (options.randomsort) {
+        fisherYatesShuffle(parts);
+      }
+
+      if (options.reverse) {
+        parts.reverse();
+      }
+
+      const out = parts.join('\n');
+      if (String(out).trim() !== '') {
+        log(out);
+      }
+
+      return;
+    } catch (e) {
+      /* istanbul ignore next */
+      self.log(e.stack);
+      /* istanbul ignore next */
+      return;
+    }
+  }
+};
+
+// This shit is gnarly.
+// Per the coreutils sort.c:
+// <none/unknown> < K/k < M < G < T < P < E < Z < Y
+const humanOrdering = {'': 0, 'K': 1, 'k': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7};
+const humanReadableSort = new RegExp(/^([0-9]+)?[\.]?[0-9]+[K|k|M|G|T|P|E|Z|Y]/g);
+function parseHumanReadableNumbers(nbr) {
+  nbr = String(nbr).replace(/(\r\n|\n|\r)/gm, '');
+  if (String(nbr).match(humanReadableSort)) {
+    const num = parseFloat(String(nbr).replace(/[a-zA-Z]/g, '').trim());
+    const group = humanOrdering[String(nbr).replace(/[^a-zA-Z]/g, '').trim()] || 0;
+    return ({
+      num,
+      group
+    });
+  }
+  const isNumber = (String(nbr).match(/^[0-9]/));
+  const stripped = (isNumber) ? parseFloat(String(nbr).replace(/[^0-9.]/g, '')) : 'NaN';
+  const result = (!isNaN(stripped)) ? stripped : -99999999999;
+  return ({
+    num: result,
+    group: 0
+  });
+}
+
+const monthOrdering = {
+  jan: 1,
+  feb: 2,
+  mar: 3,
+  apr: 4,
+  may: 5,
+  jun: 6,
+  jul: 7,
+  aug: 8,
+  sep: 9,
+  oct: 10,
+  nov: 11,
+  dec: 12
+};
+
+const months = new RegExp(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i);
+function parseMonths(str) {
+  const match = String(str).match(months);
+  if (match) {
+    return monthOrdering[String(str.slice(0, 3).toLowerCase())];
+  }
+  return 0;
+}
+
+function fisherYatesShuffle(array) {
+  let m = array.length;
+  let t;
+  let i;
+  while (m) {
+    i = Math.floor(Math.random() * m--);
+    t = array[m];
+    array[m] = array[i];
+    array[i] = t;
+  }
+  return array;
+}
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return sort;
+  }
+  vorpal.api.sort = sort;
+  vorpal
+    .command('sort [files...]')
+    .option('-M, --month-sort', 'compare (unknown) < \'JAN\' < ... < \'DEC\'')
+    .option('-h, --human-numeric-sort', 'compare human readable numbers (e.g., 2K 1G)')
+    .option('-n, --numeric-sort', 'compare according to string numerical value')
+    .option('-R, --random-sort', 'sort by random hash of keys')
+    .option('-r, --reverse', 'reverse the result of comparisons')
+    .option('-c, --check', 'check for sorted input; do not sort')
+    .option('-o, --output [file]', 'write result to file instead of standard output')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      return interfacer.call(this, {
+        command: sort,
+        args,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/touch.js b/src/commands/touch.js
new file mode 100755
index 0000000..ec911a7
--- /dev/null
+++ b/src/commands/touch.js
@@ -0,0 +1,169 @@
+'use strict';
+
+const _ = require('lodash');
+const fs = require('fs-extra');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const interfacer = require('./../util/interfacer');
+require('./../lib/sugar');
+
+const touch = {
+
+  /**
+   * Main command execution.
+   *
+   * @param {Object} args
+   * @return {Object} { status, stdout }
+   * @api public
+   */
+
+  exec(files, options) {
+    const self = this;
+    files = files || ['.'];
+    files = (!_.isArray(files)) ? [files] : files;
+    options = options || {};
+
+    // If any version of --no-create is passed, change it to false.
+    options.create = (options.create === true) ? false : options.create;
+
+    // If --time is passed, ensure a valid param is called in
+    // and map it to -a or -m, as this is the equivalent of these.
+    // Throw an error if nothing valid passed.
+    if (options.time) {
+      const a = ['access', 'atime', 'use'];
+      const m = ['modify', 'mtime'];
+      const opt = (a.indexOf(options.time) > -1) ? 'a' :
+        (m.indexOf(options.time) > -1) ? 'm' :
+        undefined;
+      if (!opt) {
+        const error =
+          `touch: invalid argument "${options.time}" for "--time"\n` +
+          'Valid arguments are:\n' +
+          '  - "atime", "access", "use"\n' +
+          '  - "mtime", "modify"\n' +
+          'Try \'touch --help\' for more information.';
+        // I think this is the stupidest thing
+        // I've ever written.
+        try {
+          throw new Error(error);
+        } catch (e) {
+          return touch.error.call(self, e);
+        }
+      } else {
+        options[opt] = true;
+      }
+    }
+
+    try {
+      let err = false;
+      for (let i = 0; i < files.length; ++i) {
+        try {
+          touch.file(files[i], options);
+        } catch (e) {
+          err = e;
+          break;
+        }
+      }
+      if (err) {
+        return touch.error.call(self, err);
+      }
+      return 0;
+    } catch (e) {
+      return touch.error.call(self, e);
+    }
+  },
+
+  /**
+   * Returns touch stderr and response codes
+   * for errors.
+   *
+   * @param {Error} e
+   * @return {Object} { status, stdout }
+   * @api private
+   */
+
+  error(e) {
+    this.log(e.message);
+    return 2;
+  },
+
+  /**
+   * Handler for a single file using touch.
+   *
+   * @param {String} path
+   * @param {Object} options
+   * @api private
+   */
+
+  file(path, options) {
+    try {
+      try {
+        fs.lstatSync(path);
+      } catch (e) {
+        // If the file doesn't exist and
+        // the user doesn't want to create it,
+        // we have no purpose in life. Goodbye.
+        if (options.create === false) {
+          throw new Error(e);
+        } else {
+          fs.closeSync(fs.openSync(path, 'wx'));
+        }
+      }
+
+      const stat = fs.statSync(path);
+      const dateToSet = (options.date) ?
+        Date.create(options.date) :
+        new Date();
+
+      if (String(dateToSet) === 'Invalid Date') {
+        throw new Error(`touch: invalid date format ${options.date}`);
+      }
+
+      // If -m, keep access time current.
+      let atime = (options.m === true) ? new Date(stat.atime) : dateToSet;
+
+      // If -a, keep mod time to current.
+      let mtime = (options.a === true) ? new Date(stat.mtime) : dateToSet;
+
+      if (options.reference !== undefined) {
+        let reference;
+        try {
+          reference = fs.statSync(options.reference);
+        } catch (e) {
+          throw new Error(`touch: failed to get attributes of ${options.reference}: No such file or directory`);
+        }
+        atime = (options.m === true) ? atime : reference.atime;
+        mtime = (options.a === true) ? mtime : reference.mtime;
+      }
+
+      fs.utimesSync(path, atime, mtime);
+      fs.utimesSync(path, atime, mtime);
+    } catch (e) {
+      throw new Error(e);
+    }
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return touch;
+  }
+  vorpal.api.touch = touch;
+  vorpal
+    .command('touch <files...>')
+    .option('-a', 'change only the access time')
+    .option('-c, --no-create', 'do not create any files')
+    .option('-d, --date [STRING]', 'parse STRING and use it instead of current time')
+    .option('-m', 'change only the modification time')
+    .option('-r, --reference [FILE]', 'use this file\'s times instead of current time')
+    .option('--time [WORD]', 'change the specified time: WORD is access, atime, or use: equivalent to -a WORD is modify or mtime: equivalent to -m')
+    .autocomplete(fsAutocomplete())
+    .action(function (args, callback) {
+      return interfacer.call(this, {
+        command: touch,
+        args: args.files || [],
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/commands/unalias.js b/src/commands/unalias.js
new file mode 100755
index 0000000..692321f
--- /dev/null
+++ b/src/commands/unalias.js
@@ -0,0 +1,97 @@
+'use strict';
+
+const _ = require('lodash');
+
+const interfacer = require('./../util/interfacer');
+
+const unalias = {
+
+  exec(args, options) {
+    args = args;
+    options = options || {};
+    const vorpal = options.vorpal;
+
+    if (!vorpal) {
+      /* istanbul ignore next */
+      throw new Error('Unalias is not programatically supported.');
+    }
+
+    vorpal._aliases = vorpal._aliases || [];
+
+    if (_.isString(args)) {
+      args = String(args).split(' ');
+      args = args.filter(str => {
+        return String(str).trim() !== '';
+      });
+    }
+
+    // Validate no input with help.
+    if ((args === undefined || args.length < 1 || args === '') && !options.a) {
+      this.log('unalias: usage: unalias [-a] name [name ...]');
+      return 1;
+    }
+
+    // Pull list of aliases
+    let all;
+    try {
+      all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      /* istanbul ignore next */
+      all = [];
+      /* istanbul ignore next */
+      vorpal.localStorage.removeItem('aliases');
+    }
+
+    if (options.a) {
+      args = all;
+    }
+
+    // Remove each alias in the list.
+    for (let i = 0; i < args.length; ++i) {
+      const key = args[i];
+      const item = vorpal.localStorage.getItem(`alias|${key}`);
+      if (item !== undefined && item !== null) {
+        vorpal.localStorage.removeItem(`alias|${key}`);
+      } else {
+        this.log(`-cash: unalias: ${key}: not found`);
+      }
+      all = all.filter(str => {
+        return !(str === key);
+      });
+    }
+
+    // Rebuild alias lists.
+    const aliases = {};
+    /* istanbul ignore next */
+    for (let i = 0; i < all.length; ++i) {
+      const item = vorpal.localStorage.getItem(`alias|${all[i]}`);
+      if (item !== undefined && item !== null) {
+        aliases[all[i]] = item;
+      }
+    }
+    vorpal._aliases = aliases;
+
+    vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+    return 0;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return unalias;
+  }
+  vorpal.api.unalias = unalias;
+  vorpal
+    .command('unalias [name...]')
+    .option('-a', 'remove all alias definitions')
+    .action(function (args, callback) {
+      args.options = args.options || {};
+      args.options.vorpal = vorpal;
+      return interfacer.call(this, {
+        command: unalias,
+        args: args.name,
+        options: args.options,
+        callback
+      });
+    });
+};
diff --git a/src/delimiter.js b/src/delimiter.js
new file mode 100755
index 0000000..f401ac8
--- /dev/null
+++ b/src/delimiter.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const os = require('os');
+const username = require('username');
+
+const pathConverter = require('./util/converter.path');
+
+module.exports = {
+
+  refresh(vorpal, cb) {
+    cb = cb || function () {};
+    const self = this;
+    username(function (err, username) {
+      if (!err) {
+        const user = username;
+        const host = String(os.hostname()).split('.')[0];
+        const home = pathConverter.unix(self.getHomeDir());
+        let cwd = pathConverter.unix(process.cwd());
+        cwd = cwd.replace(home, '~');
+        let delimiter = `${user}@${host}:${cwd}$`;
+        // If we're on linux-based systems, color
+        // the prompt so we don't get confused.
+        if (os.platform().indexOf('win') === -1) {
+          delimiter = `\u001b[32m${delimiter}\u001b[39m`;
+        }
+        vorpal.delimiter(delimiter);
+      }
+      cb(err);
+    });
+  },
+
+  getHomeDir() {
+    return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
+  }
+};
diff --git a/src/help.js b/src/help.js
new file mode 100755
index 0000000..5d76312
--- /dev/null
+++ b/src/help.js
@@ -0,0 +1,52 @@
+'use strict';
+
+const pad = require('./util/pad');
+
+const commands = [
+  'alias [-p] [name=[value]]',
+  'cat [-AbeEnstTv] [files ...]',
+  'cd [dir]',
+  'cp [-fnr] source ... dest',
+  'echo [eE] [arg ...]',
+  'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]',
+  'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l',
+  'less [files ...]',
+  'ls [-aAdFhilQrRStUwx1] [paths ...]',
+  'mkdir [-pv] [directories ...]',
+  'mv [-fnv] source ... dest',
+  'pwd [files ...]',
+  'rm [-frR] [files ...]',
+  'sort [-chMnrR] [-o file] [files ...]',
+  'touch [-acm] [-d date] [-r ref] [--time word] file ...',
+  'unalias [-a] name [names ...]'
+];
+
+function chop(str, len) {
+  let res = String(str).slice(0, len - 2);
+  res = (res.length === len - 2) ? `${res}>` : res;
+  return res;
+}
+
+module.exports = function () {
+  const version = require('./../package.json').version;
+  let result = '';
+
+  result += `Cash, version ${version}\n`;
+  result += `These shell commands are defined internally.  Type \`help\' to see this list.\n`;
+  result += `Type \`help name\' to find out more about the function \`name\'.\n`;
+  result += `Use \`info cash\' to find out more about the shell in general.\n`;
+  result += `\n`;
+
+  const half = Math.floor(commands.length / 2);
+  const width = Math.floor((process.stdout.columns - 3) / 2);
+  const lhalf = Math.ceil(commands.length / 2);
+  const padding = ((commands.length % 2) === 1) ? 1 : 0;
+  for (let i = 0; i < lhalf; ++i) {
+    const colA = pad(chop(commands[i], width), width);
+    const colB = pad(chop(commands[half + i + padding] || '', width), width);
+    const line = (i === lhalf - 1) ? '' : '\n';
+    result += ` ${colA} ${colB}${line}`;
+  }
+
+  return result;
+};
diff --git a/src/help/alias.js b/src/help/alias.js
new file mode 100755
index 0000000..99fcf77
--- /dev/null
+++ b/src/help/alias.js
@@ -0,0 +1,17 @@
+module.exports = `
+Usage: alias [OPTION] [name[=value] ...]
+Define or display aliases.
+
+Without arguments, \`alias' prints the list of aliases in the reusable
+form \`alias NAME=VALUE' on standard output.
+
+Otherwise, an alias is defined for each NAME whose VALUE is given.
+A trailing space in VALUE causes the next word to be checked for
+alias substitution when the alias is expanded.
+
+  -p           print all defined aliases in a reusable format
+      --help   display this help and exit
+
+Report alias bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/cat.js b/src/help/cat.js
new file mode 100755
index 0000000..1e871c2
--- /dev/null
+++ b/src/help/cat.js
@@ -0,0 +1,24 @@
+module.exports = `
+Usage: cat [OPTION]... [FILE]...
+Concatenate FILE(s), or standard input, to standard output.
+
+  -A, --show-all           equivalent to -vET
+  -b, --number-nonblank    number nonempty output lines, overrides -n
+  -e                       equivalent to -vE
+  -E, --show-ends          display $ at end of each line
+  -n, --number             number all output lines
+  -s, --squeeze-blank      suppress repeated empty output lines
+  -t                       equivalent to -vT
+  -T, --show-tabs          display TAB characters as ^I
+  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB
+      --help               display this help and exit
+
+With no FILE, or when FILE is -, read standard input.
+
+Examples:
+  cat f - g  Output f's contents, then standard input, then g's contents.
+  cat        Copy standard input to standard output.
+
+Report cat bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/cd.js b/src/help/cd.js
new file mode 100755
index 0000000..bdf72d7
--- /dev/null
+++ b/src/help/cd.js
@@ -0,0 +1,10 @@
+module.exports = `
+Usage: cd [DIR]...
+Change the cash working directory.
+
+Change the current directory to DIR.  The default DIR is the value of the
+HOME shell variable.
+
+Report cd bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/cp.js b/src/help/cp.js
new file mode 100755
index 0000000..45daf74
--- /dev/null
+++ b/src/help/cp.js
@@ -0,0 +1,16 @@
+module.exports = `
+Usage: cp [OPTION]... [-T] SOURCE DEST
+  or:  cp [OPTION]... SOURCE... DIRECTORY
+Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
+
+  -f, --force           if an existing destination file cannot be
+                          opened, remove it and try again (this option
+                          is ignored when the -n option is also used)
+  -n, --no-clobber      do not overwrite an existing file (overrides
+                          a previous -i option)
+  -R, -r, --recursive   copy directories recursively
+      --help            display this help and exit
+
+Report cp bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/echo.js b/src/help/echo.js
new file mode 100755
index 0000000..fde7144
--- /dev/null
+++ b/src/help/echo.js
@@ -0,0 +1,22 @@
+module.exports = `
+Usage: echo [OPTION]... [ARG ...]
+Write arguments to the standard output.
+
+Display the ARGs, separated by a single space character and followed by a
+newline, on the standard output.
+
+  -e           enable interpretation of the following backslash escapes
+  -e           explicitly suppress interpretation of backslash escapes
+      --help   display this help and exit
+
+  \`echo' interprets the following backslash-escaped characters:
+    \b         backspace
+    \c         suppress further output
+    \n         new line
+    \r         carriage return
+    \t         horizontal tab
+    \\         backslash
+
+Report echo bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/grep.js b/src/help/grep.js
new file mode 100755
index 0000000..37fbab2
--- /dev/null
+++ b/src/help/grep.js
@@ -0,0 +1,33 @@
+module.exports = `
+Usage: grep [OPTION]... PATTERN [FILE]...
+Search for PATTERN in each FILE or standard input.
+PATTERN is, by default, a basic regular expression (BRE).
+Example: grep -i 'hello world' menu.h main.c
+
+iwsvmbnHhqr
+
+Regexp selection and interpretation:
+  -i, --ignore-case         ignore case distinctions
+  -w, --word-regexp         force PATTERN to match only whole words
+
+Miscellaneous:
+  -s, --no-messages         suppress error messages
+  -v, --invert-match        select non-matching lines
+      --help                display this help and exit
+
+Output control:
+  -n, --line-number         print line number with output lines
+  -H, --with-filename       print the file name for each match
+  -h, --no-filename         suppress the file name prefix on output
+  -q, --quiet, --silent     suppress all normal output
+  -r, --recursive           like --directories=recurse
+      --include <FILE_PATTERN>  search only files that match FILE_PATTERN
+
+When FILE is -, read standard input.  With no FILE, read . if a command-line
+-r is given, - otherwise.  If fewer than two FILEs are given, assume -h.
+Exit status is 0 if any line is selected, 1 otherwise;
+if any error occurs and -q is not given, the exit status is 2.
+
+Report grep bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/kill.js b/src/help/kill.js
new file mode 100755
index 0000000..13c82bb
--- /dev/null
+++ b/src/help/kill.js
@@ -0,0 +1,22 @@
+module.exports = `
+Usage: kill [OPTION] pid | jobspec ... or kill -l [sigspec]
+Send a signal to a job.
+
+Send the processes identified by PID or JOBSPEC the signal named by
+SIGSPEC or SIGNUM.  If neither SIGSPEC nor SIGNUM is present, then
+SIGTERM is assumed.
+
+  -s sig         SIG is a signal name
+  -n sig         SIG is a signal number
+  -l [sigspec]   list the signal names; if arguments follow \`-l' they
+                 are assumed to be signal numbers for which names
+                 should be listed
+      --help     display this help and exit
+
+Exit status:
+  0   if OK,
+  1   if an invalid option is given or an error occurs.
+
+Report kill bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/ls.js b/src/help/ls.js
new file mode 100755
index 0000000..5b624d5
--- /dev/null
+++ b/src/help/ls.js
@@ -0,0 +1,33 @@
+module.exports = `
+Usage: ls [OPTION]... [FILE]...
+List information about the FILEs (the current directory by default).
+Sort entries alphabetically if none of -tSU nor --sort is specified.
+
+  -a, --all                  do not ignore entries starting with .
+  -A, --almost-all           do not list implied . and ..
+  -d, --directory            list directory entries instead of contents,
+                               and do not dereference symbolic links
+  -f                         do not sort, enable -aU, disable -ls --color
+  -F, --classify             append indicator (one of */=>@|) to entries
+  -h, --human-readable       with -l, print sizes in human readable format
+  -i, --inode                print the index number of each file
+  -l                         use a long listing format
+  -q, --hide-control-chars   print ? instead of non graphic characters
+  -r, --reverse              reverse order while sorting
+  -R, --recursive            list subdirectories recursively
+  -S                         sort by file size
+  -t                         sort by modification time, newest first
+  -U                         do not sort; list entries in directory order
+  -w, --width=COLS           assume screen width instead of current value
+  -x                         list entries by lines instead of by columns
+  -1                         list one file per line
+      --help                 display this help and exit
+
+Exit status:
+  0   if OK,
+  1   if minor problems (e.g., cannot access subdirectory),
+  2   if serious trouble (e.g., cannot access command-line argument).
+
+Report ls bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/mkdir.js b/src/help/mkdir.js
new file mode 100755
index 0000000..7bb5b33
--- /dev/null
+++ b/src/help/mkdir.js
@@ -0,0 +1,11 @@
+module.exports = `
+Usage: mkdir [OPTION]... DIRECTORY...
+Create the DIRECTORY(ies), if they do not already exist.
+
+  -p, --parents     no error if existing, make parent directories as needed
+  -v, --verbose     print a message for each created directory
+      --help        display this help and exit
+
+Report mkdir bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/mv.js b/src/help/mv.js
new file mode 100755
index 0000000..d23e1ad
--- /dev/null
+++ b/src/help/mv.js
@@ -0,0 +1,18 @@
+module.exports = `
+Usage: mv [OPTION]... [-T] SOURCE DEST
+  or:  mv [OPTION]... SOURCE... DIRECTORY
+  or:  mv [OPTION]... -t DIRECTORY SOURCE...
+Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
+
+  -f, --force                  do not prompt before overwriting
+  -n, --no-clobber             do not overwrite an existing file
+      --striptrailingslashes   remove any trailing slashes from each SOURCE
+                                 argument
+  -v, --verbose                explain what is being done
+      --help                   display this help and exit
+
+If you specify -f and -n, only -f takes effect.
+
+Report mv bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/pwd.js b/src/help/pwd.js
new file mode 100755
index 0000000..9e98510
--- /dev/null
+++ b/src/help/pwd.js
@@ -0,0 +1,14 @@
+module.exports = `
+Usage: pwd [-LP]
+Print the name of the current working directory.
+
+      --help        display this help and exit
+
+Exit status:
+  0   if OK,
+  1   if an invalid option is given or the current directory
+      cannot be read.
+
+Report pwd bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/rm.js b/src/help/rm.js
new file mode 100755
index 0000000..08e14a5
--- /dev/null
+++ b/src/help/rm.js
@@ -0,0 +1,22 @@
+module.exports = `
+Usage: rm [OPTION]... FILE...
+Remove (unlink) the FILE(s).
+
+  -f, --force           ignore nonexistent files and arguments, never prompt
+  -r, -R, --recursive   remove directories and their contents recursively
+      --help            display this help and exit
+
+By default, rm does not remove directories.  Use the --recursive (-r or -R)
+option to remove each listed directory, too, along with all of its contents.
+
+To remove a file whose name starts with a '-', for example '-foo',
+use one of these commands:
+  rm -- -foo
+  rm ./-foo
+
+Note that if you use rm to remove a file, it might be possible to recover
+some of its contents, given sufficient expertise and/or time.
+
+Report rm bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/sort.js b/src/help/sort.js
new file mode 100755
index 0000000..f80cf7d
--- /dev/null
+++ b/src/help/sort.js
@@ -0,0 +1,22 @@
+module.exports = `
+Usage: sort [OPTION]... [FILE]...
+Write sorted concatenation of all FILE(s) to standard output.
+
+Ordering options:
+  -M, --month-sort            compare (unknown) < 'JAN' < ... < 'DEC'
+  -h, --human-numeric-sort    compare human readable numbers (e.g., 2K 1G)
+  -n, --numeric-sort          compare according to string numerical value
+  -R, --random-sort           sort by random hash of keys
+  -r, --reverse               reverse the result of comparisons
+
+Other options:
+  -c, --check,
+      --check=diagnose-first  check for sorted input; do not sort
+  -o, --output=FILE           write result to FILE instead of standard output
+      --help                  display this help and exit
+
+With no FILE, or when FILE is -, read standard input.
+
+Report sort bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/touch.js b/src/help/touch.js
new file mode 100755
index 0000000..66078f3
--- /dev/null
+++ b/src/help/touch.js
@@ -0,0 +1,20 @@
+module.exports = `
+Usage: touch [OPTION]... FILE...
+Update the access and modification times of each FILE to the current time.
+
+A FILE argument that does not exist is created empty, unless -c is
+supplied.
+
+  -a                      change only the access time
+  -c, --no-create         do not create any files
+  -d, --date <STRING>     parse STRING and use it instead of current time
+  -m                      change only the modification time
+  -r, --reference <FILE>  use this file's times instead of current time
+      --time <WORD>       change the specified time:
+                            WORD is access, atime, or use: equivalent to -a
+                            WORD is modify or mtime: equivalent to -m
+      --help              display this help and exit
+
+Report touch bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/help/unalias.js b/src/help/unalias.js
new file mode 100755
index 0000000..b796775
--- /dev/null
+++ b/src/help/unalias.js
@@ -0,0 +1,14 @@
+module.exports = `
+Usage: unalias [OPTION] name ...
+Remove each name from the list of defined aliases.
+
+  -a           remove all alias definitions
+      --help   display this help and exit
+
+Exit status:
+  0   if OK,
+  1   if a name is not an existing alias.
+
+Report unalias bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/src/index.js b/src/index.js
new file mode 100755
index 0000000..22ebc1b
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,182 @@
+'use strict';
+
+const _ = require('lodash');
+const os = require('os');
+const Vorpal = require('vorpal');
+
+const commands = require('./../commands.json');
+const help = require('./help');
+const interfacer = require('./util/interfacer');
+
+let cmds;
+
+const app = {
+
+  commands: commands.commands,
+
+  importedCommands: commands.importedCommands,
+
+  vorpal: new Vorpal(),
+
+  _cwd: process.cwd(),
+
+  _fatal: false,
+
+  export(str, cbk) {
+    cbk = cbk || function () {};
+    const options = {
+      fatal: app._fatal || false
+    };
+    // Hook stdin, execute the command and
+    // then return it all.
+    const intercept = require('./util/intercept');
+    let out = '';
+    const unhook = intercept(function (str) {
+      out += `${str}\n`;
+      return '';
+    });
+    app.vorpal.execSync(str, options);
+    unhook();
+    return String(out).replace(/\n$/, '');
+  },
+
+  load() {
+    const self = this;
+    self.vorpal.api = {};
+    this.commands.forEach(function (cmd) {
+      if (self.importedCommands.indexOf(cmd) > -1) {
+        return;
+      }
+      try {
+        const mod = require(`./commands/${cmd}.js`);
+        let help;
+        try {
+          help = require(`./help/${cmd}.js`);
+          help = String(help).replace(/^\n|\n$/g, '');
+        } catch (e) {
+          // .. whatever
+        }
+        self.vorpal.use(mod, {
+          parent: self
+        });
+        const cmdObj = self.vorpal.find(cmd);
+        if (cmdObj && help) {
+          /* istanbul ignore next */
+          cmdObj.help(function (args, cb) {
+            cb(help);
+          });
+        }
+      } catch (e) {
+        /* istanbul ignore next */
+        self.vorpal.log(`Error loading command ${cmd}: `, e);
+      }
+    });
+    this.importedCommands.forEach(function (cmd) {
+      try {
+        const mod = require(`vorpal-${cmd}`);
+        self.vorpal.use(mod, {
+          parent: self
+        });
+      } catch (e) {
+        /* istanbul ignore next */
+        self.vorpal.log(`Error loading command ${cmd}: `, e);
+      }
+    });
+
+    // If we're running Windows, register
+    // process spawning for Windows child processes.
+    // If on Linux, just does registers the .catch command.
+    const windows = require('./windows');
+    windows.registerCommands(self);
+
+    for (const cmd in app.vorpal.api) {
+      if (app.vorpal.api.hasOwnProperty(cmd)) {
+        app.export[cmd] = function (args, options, callback) {
+          callback = callback || function () {};
+          options = options || {};
+          options.vorpal = app.vorpal;
+          return interfacer.call(this, {
+            command: app.vorpal.api[cmd],
+            args,
+            options,
+            callback,
+            async: app.vorpal.api[cmd].async || false,
+            silent: true
+          });
+        };
+      }
+    }
+
+    app.vorpal
+      .history('cash')
+      .localStorage('cash')
+      .help(help);
+
+    app.vorpal
+      .find('exit')
+      .action(function () {
+        /* istanbul ignore next */
+        process.exit(1);
+      });
+
+    // Load aliases
+    let all;
+    try {
+      all = JSON.parse(app.vorpal.localStorage.getItem('aliases') || []);
+    } catch (e) {
+      /* istanbul ignore next */
+      all = [];
+      /* istanbul ignore next */
+      app.vorpal.localStorage.removeItem('aliases');
+    }
+    const aliases = {};
+    /* istanbul ignore next */
+    for (let i = 0; i < all.length; ++i) {
+      const item = app.vorpal.localStorage.getItem(`alias|${all[i]}`);
+      if (item !== undefined && item !== null) {
+        aliases[all[i]] = item;
+      }
+    }
+    app.vorpal._aliases = aliases;
+
+    // Override SIGINT to be ignored,
+    // and if the user is insistent, give
+    // a helpful message. The purpose of this
+    // is to give a full shell feel, not an
+    // application running over the shell.
+    // Skip this on linux, as its mainly
+    // for dev testing.
+    /* istanbul ignore next */
+    if (os.platform().indexOf('win') > -1) {
+      let counter = 0;
+      setInterval(function () {
+        counter = (counter > 0) ? 0 : counter;
+      }, 3000);
+      app.vorpal.sigint(function () {
+        counter++;
+        app.vorpal.ui.submit('');
+        if (counter > 5) {
+          app.vorpal.log('(to quit Cash, use the "exit" command)');
+          counter -= 10000;
+        }
+        return;
+      });
+    }
+
+    app.export.vorpal = app.vorpal;
+    _.extend(app.export, cmds);
+    return this;
+  }
+};
+
+cmds = {
+  /* istanbul ignore next */
+  show() {
+    /* istanbul ignore next */
+    app.vorpal.show();
+  }
+};
+
+app.load();
+
+module.exports = app.export;
diff --git a/src/lib/sugar.js b/src/lib/sugar.js
new file mode 100755
index 0000000..36acdcf
--- /dev/null
+++ b/src/lib/sugar.js
@@ -0,0 +1,79 @@
+/*
+ *  Sugar Library v1.4.1
+ *
+ *  Freely distributable and licensed under the MIT-style license.
+ *  Copyright (c) 2014 Andrew Plummer
+ *  http://sugarjs.com/
+ *
+ * ---------------------------- */
+/* istanbul ignore next */
+(function(){function aa(a){return function(){return a}}
+/* istanbul ignore next */
+var m=Object,p=Array,q=RegExp,r=Date,s=String,t=Number,u=Math,ba="undefined"!==typeof global?global:this,v=m.prototype.toString,da=m.prototype.hasOwnProperty,ea=m.defineProperty&&m.defineProperties,fa="function"===typeof q(),ga=!("0"in new s("a")),ia={},ja=/^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,w="Boolean Number String Array Date RegExp Function".split(" "),la=ka("boolean",w[0]),y=ka("number",w[1]),z=ka("string",w[2]),A=ma(w[3]),C=ma(w[4]),D=ma(w[5]),F=ma(w[6]);
+/* istanbul ignore next */
+function ma(a){var b="Array"===a&&p.isArray||function(b,d){return(d||v.call(b))==="[object "+a+"]"};return ia[a]=b}function ka(a,b){function c(c){return G(c)?v.call(c)==="[object "+b+"]":typeof c===a}return ia[b]=c}
+function na(a){a.SugarMethods||(oa(a,"SugarMethods",{}),H(a,!1,!0,{extend:function(b,c,d){H(a,!1!==d,c,b)},sugarRestore:function(){return pa(this,a,arguments,function(a,c,d){oa(a,c,d.method)})},sugarRevert:function(){return pa(this,a,arguments,function(a,c,d){d.existed?oa(a,c,d.original):delete a[c]})}}))}function H(a,b,c,d){var e=b?a.prototype:a;na(a);I(d,function(d,f){var h=e[d],l=J(e,d);F(c)&&h&&(f=qa(h,f,c));!1===c&&h||oa(e,d,f);a.SugarMethods[d]={method:f,existed:l,original:h,instance:b}})}
+function K(a,b,c,d,e){var g={};d=z(d)?d.split(","):d;d.forEach(function(a,b){e(g,a,b)});H(a,b,c,g)}function pa(a,b,c,d){var e=0===c.length,g=L(c),f=!1;I(b.SugarMethods,function(b,c){if(e||-1!==g.indexOf(b))f=!0,d(c.instance?a.prototype:a,b,c)});return f}function qa(a,b,c){return function(d){return c.apply(this,arguments)?b.apply(this,arguments):a.apply(this,arguments)}}function oa(a,b,c){ea?m.defineProperty(a,b,{value:c,configurable:!0,enumerable:!1,writable:!0}):a[b]=c}
+function L(a,b,c){var d=[];c=c||0;var e;for(e=a.length;c<e;c++)d.push(a[c]),b&&b.call(a,a[c],c);return d}function sa(a,b,c){var d=a[c||0];A(d)&&(a=d,c=0);L(a,b,c)}function ta(a){if(!a||!a.call)throw new TypeError("Callback is not callable");}function M(a){return void 0!==a}function N(a){return void 0===a}function J(a,b){return!!a&&da.call(a,b)}function G(a){return!!a&&("object"===typeof a||fa&&D(a))}function ua(a){var b=typeof a;return null==a||"string"===b||"number"===b||"boolean"===b}
+function va(a,b){b=b||v.call(a);try{if(a&&a.constructor&&!J(a,"constructor")&&!J(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}return!!a&&"[object Object]"===b&&"hasOwnProperty"in a}function I(a,b){for(var c in a)if(J(a,c)&&!1===b.call(a,c,a[c],a))break}function wa(a,b){for(var c=0;c<a;c++)b(c)}function xa(a,b){I(b,function(c){a[c]=b[c]});return a}function ya(a){ua(a)&&(a=m(a));if(ga&&z(a))for(var b=a,c=0,d;d=b.charAt(c);)b[c++]=d;return a}function O(a){xa(this,ya(a))}
+O.prototype.constructor=m;var P=u.abs,za=u.pow,Aa=u.ceil,Q=u.floor,R=u.round,Ca=u.min,S=u.max;function Da(a,b,c){var d=za(10,P(b||0));c=c||R;0>b&&(d=1/d);return c(a*d)/d}var Ea=48,Fa=57,Ga=65296,Ha=65305,Ia=".",Ja="",Ka={},La;function Ma(){return"\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u2028\u2029\u3000\ufeff"}function Na(a,b){var c="";for(a=a.toString();0<b;)if(b&1&&(c+=a),b>>=1)a+=a;return c}
+function Oa(a,b){var c,d;c=a.replace(La,function(a){a=Ka[a];a===Ia&&(d=!0);return a});return d?parseFloat(c):parseInt(c,b||10)}function T(a,b,c,d){d=P(a).toString(d||10);d=Na("0",b-d.replace(/\.\d+/,"").length)+d;if(c||0>a)d=(0>a?"-":"+")+d;return d}function Pa(a){if(11<=a&&13>=a)return"th";switch(a%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}}
+function Qa(a,b){function c(a,c){if(a||-1<b.indexOf(c))d+=c}var d="";b=b||"";c(a.multiline,"m");c(a.ignoreCase,"i");c(a.global,"g");c(a.u,"y");return d}function Ra(a){z(a)||(a=s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g,"\\$1")}function U(a,b){return a["get"+(a._utc?"UTC":"")+b]()}function Sa(a,b,c){return a["set"+(a._utc&&"ISOWeek"!=b?"UTC":"")+b](c)}
+function Ta(a,b){var c=typeof a,d,e,g,f,h,l,n;if("string"===c)return a;g=v.call(a);d=va(a,g);e=A(a,g);if(null!=a&&d||e){b||(b=[]);if(1<b.length)for(l=b.length;l--;)if(b[l]===a)return"CYC";b.push(a);d=a.valueOf()+s(a.constructor);f=e?a:m.keys(a).sort();l=0;for(n=f.length;l<n;l++)h=e?l:f[l],d+=h+Ta(a[h],b);b.pop()}else d=-Infinity===1/a?"-0":s(a&&a.valueOf?a.valueOf():a);return c+g+d}function Ua(a,b){return a===b?0!==a||1/a===1/b:Va(a)&&Va(b)?Ta(a)===Ta(b):!1}
+function Va(a){var b=v.call(a);return ja.test(b)||va(a,b)}function Wa(a,b,c){var d,e=a.length,g=b.length,f=!1!==b[g-1];if(!(g>(f?1:2)))return Xa(a,e,b[0],f,c);d=[];L(b,function(b){if(la(b))return!1;d.push(Xa(a,e,b,f,c))});return d}function Xa(a,b,c,d,e){d&&(c%=b,0>c&&(c=b+c));return e?a.charAt(c):a[c]}function Ya(a,b){K(b,!0,!1,a,function(a,b){a[b+("equal"===b?"s":"")]=function(){return m[b].apply(null,[this].concat(L(arguments)))}})}na(m);I(w,function(a,b){na(ba[b])});var Za,$a;
+for($a=0;9>=$a;$a++)Za=s.fromCharCode($a+Ga),Ja+=Za,Ka[Za]=s.fromCharCode($a+Ea);Ka[","]="";Ka["\uff0e"]=Ia;Ka[Ia]=Ia;La=q("["+Ja+"\uff0e,"+Ia+"]","g");
+"use strict";H(m,!1,!1,{keys:function(a){var b=[];if(!G(a)&&!D(a)&&!F(a))throw new TypeError("Object required");I(a,function(a){b.push(a)});return b}});
+function ab(a,b,c,d){var e=a.length,g=-1==d,f=g?e-1:0;c=isNaN(c)?f:parseInt(c>>0);0>c&&(c=e+c);if(!g&&0>c||g&&c>=e)c=f;for(;g&&0<=c||!g&&c<e;){if(a[c]===b)return c;c+=d}return-1}function bb(a,b,c,d){var e=a.length,g=0,f=M(c);ta(b);if(0!=e||f)f||(c=a[d?e-1:g],g++);else throw new TypeError("Reduce called on empty array with no initial value");for(;g<e;)f=d?e-g-1:g,f in a&&(c=b(c,a[f],f,a)),g++;return c}function cb(a){if(0===a.length)throw new TypeError("First argument must be defined");}H(p,!1,!1,{isArray:function(a){return A(a)}});
+H(p,!0,!1,{every:function(a,b){var c=this.length,d=0;for(cb(arguments);d<c;){if(d in this&&!a.call(b,this[d],d,this))return!1;d++}return!0},some:function(a,b){var c=this.length,d=0;for(cb(arguments);d<c;){if(d in this&&a.call(b,this[d],d,this))return!0;d++}return!1},map:function(a,b){b=arguments[1];var c=this.length,d=0,e=Array(c);for(cb(arguments);d<c;)d in this&&(e[d]=a.call(b,this[d],d,this)),d++;return e},filter:function(a){var b=arguments[1],c=this.length,d=0,e=[];for(cb(arguments);d<c;)d in
+this&&a.call(b,this[d],d,this)&&e.push(this[d]),d++;return e},indexOf:function(a,b){return z(this)?this.indexOf(a,b):ab(this,a,b,1)},lastIndexOf:function(a,b){return z(this)?this.lastIndexOf(a,b):ab(this,a,b,-1)},forEach:function(a,b){var c=this.length,d=0;for(ta(a);d<c;)d in this&&a.call(b,this[d],d,this),d++},reduce:function(a,b){return bb(this,a,b)},reduceRight:function(a,b){return bb(this,a,b,!0)}});
+H(Function,!0,!1,{bind:function(a){var b=this,c=L(arguments,null,1),d;if(!F(this))throw new TypeError("Function.prototype.bind called on a non-function");d=function(){return b.apply(b.prototype&&this instanceof b?this:a,c.concat(L(arguments)))};d.prototype=this.prototype;return d}});H(r,!1,!1,{now:function(){return(new r).getTime()}});
+(function(){var a=Ma().match(/^\s+$/);try{s.prototype.trim.call([1])}catch(b){a=!1}H(s,!0,!a,{trim:function(){return this.toString().trimLeft().trimRight()},trimLeft:function(){return this.replace(q("^["+Ma()+"]+"),"")},trimRight:function(){return this.replace(q("["+Ma()+"]+$"),"")}})})();
+(function(){var a=new r(r.UTC(1999,11,31)),a=a.toISOString&&"1999-12-31T00:00:00.000Z"===a.toISOString();K(r,!0,!a,"toISOString,toJSON",function(a,c){a[c]=function(){return T(this.getUTCFullYear(),4)+"-"+T(this.getUTCMonth()+1,2)+"-"+T(this.getUTCDate(),2)+"T"+T(this.getUTCHours(),2)+":"+T(this.getUTCMinutes(),2)+":"+T(this.getUTCSeconds(),2)+"."+T(this.getUTCMilliseconds(),3)+"Z"}})})();
+"use strict";
+var W,Ib,Jb="ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),Kb="({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",Lb={},Mb,Nb,Ob,Pb=[],Qb={},X={yyyy:function(a){return U(a,"FullYear")},yy:function(a){return U(a,"FullYear")%100},ord:function(a){a=U(a,"Date");return a+Pa(a)},tz:function(a){return a.getUTCOffset()},isotz:function(a){return a.getUTCOffset(!0)},
+Z:function(a){return a.getUTCOffset()},ZZ:function(a){return a.getUTCOffset().replace(/(\d{2})$/,":$1")}},Rb=[{name:"year",method:"FullYear",k:!0,b:function(a){return 864E5*(365+(a?a.isLeapYear()?1:0:0.25))}},{name:"month",error:0.919,method:"Month",k:!0,b:function(a,b){var c=30.4375,d;a&&(d=a.daysInMonth(),b<=d.days()&&(c=d));return 864E5*c}},{name:"week",method:"ISOWeek",b:aa(6048E5)},{name:"day",error:0.958,method:"Date",k:!0,b:aa(864E5)},{name:"hour",method:"Hours",b:aa(36E5)},{name:"minute",
+method:"Minutes",b:aa(6E4)},{name:"second",method:"Seconds",b:aa(1E3)},{name:"millisecond",method:"Milliseconds",b:aa(1)}],Sb={};function Tb(a){xa(this,a);this.g=Pb.concat()}
+Tb.prototype={getMonth:function(a){return y(a)?a-1:this.months.indexOf(a)%12},getWeekday:function(a){return this.weekdays.indexOf(a)%7},addFormat:function(a,b,c,d,e){var g=c||[],f=this,h;a=a.replace(/\s+/g,"[,. ]*");a=a.replace(/\{([^,]+?)\}/g,function(a,b){var d,e,h,B=b.match(/\?$/);h=b.match(/^(\d+)\??$/);var k=b.match(/(\d)(?:-(\d))?/),E=b.replace(/[^a-z]+$/,"");h?d=f.tokens[h[1]]:f[E]?d=f[E]:f[E+"s"]&&(d=f[E+"s"],k&&(e=[],d.forEach(function(a,b){var c=b%(f.units?8:d.length);c>=k[1]&&c<=(k[2]||
+k[1])&&e.push(a)}),d=e),d=Ub(d));h?h="(?:"+d+")":(c||g.push(E),h="("+d+")");B&&(h+="?");return h});b?(b=Vb(f,e),e=["t","[\\s\\u3000]"].concat(f.timeMarker),h=a.match(/\\d\{\d,\d\}\)+\??$/),Wb(f,"(?:"+b+")[,\\s\\u3000]+?"+a,Jb.concat(g),d),Wb(f,a+"(?:[,\\s]*(?:"+e.join("|")+(h?"+":"*")+")"+b+")?",g.concat(Jb),d)):Wb(f,a,g,d)}};
+function Xb(a,b,c){var d,e,g=b[0],f=b[1],h=b[2];b=a[c]||a.relative;if(F(b))return b.call(a,g,f,h,c);e=a.units[8*(a.plural&&1<g?1:0)+f]||a.units[f];a.capitalizeUnit&&(e=Yb(e));d=a.modifiers.filter(function(a){return"sign"==a.name&&a.value==(0<h?1:-1)})[0];return b.replace(/\{(.*?)\}/g,function(a,b){switch(b){case "num":return g;case "unit":return e;case "sign":return d.src}})}function Zb(a,b){b=b||a.code;return"en"===b||"en-US"===b?!0:a.variant}
+function $b(a,b){return b.replace(q(a.num,"g"),function(b){return ac(a,b)||""})}function ac(a,b){var c;return y(b)?b:b&&-1!==(c=a.numbers.indexOf(b))?(c+1)%10:1}function Y(a,b){var c;z(a)||(a="");c=Sb[a]||Sb[a.slice(0,2)];if(!1===b&&!c)throw new TypeError("Invalid locale.");return c||Ib}
+function bc(a,b){function c(a){var b=h[a];z(b)?h[a]=b.split(","):b||(h[a]=[])}function d(a,b){a=a.split("+").map(function(a){return a.replace(/(.+):(.+)$/,function(a,b,c){return c.split("|").map(function(a){return b+a}).join("|")})}).join("|");a.split("|").forEach(b)}function e(a,b,c){var e=[];h[a].forEach(function(a,f){b&&(a+="+"+a.slice(0,3));d(a,function(a,b){e[b*c+f]=a.toLowerCase()})});h[a]=e}function g(a,b,c){a="\\d{"+a+","+b+"}";c&&(a+="|(?:"+Ub(h.numbers)+")+");return a}function f(a,b){h[a]=
+h[a]||b}var h,l;h=new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l=!h.monthSuffix;e("months",l,12);e("weekdays",l,7);e("units",!1,8);e("numbers",!1,10);f("code",a);f("date",g(1,2,h.digitDate));f("year","'\\d{2}|"+g(4,4));f("num",function(){var a=["-?\\d+"].concat(h.articles);h.numbers&&(a=a.concat(h.numbers));return Ub(a)}());(function(){var a=[];h.i={};h.modifiers.push({name:"day",src:"yesterday",value:-1});
+h.modifiers.push({name:"day",src:"today",value:0});h.modifiers.push({name:"day",src:"tomorrow",value:1});h.modifiers.forEach(function(b){var c=b.name;d(b.src,function(d){var e=h[c];h.i[d]=b;a.push({name:c,src:d,value:b.value});h[c]=e?e+"|"+d:d})});h.day+="|"+Ub(h.weekdays);h.modifiers=a})();h.monthSuffix&&(h.month=g(1,2),h.months="1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function(a){return a+h.monthSuffix}));h.full_month=g(1,2)+"|"+Ub(h.months);0<h.timeSuffixes.length&&h.addFormat(Vb(h),!1,Jb);
+h.addFormat("{day}",!0);h.addFormat("{month}"+(h.monthSuffix||""));h.addFormat("{year}"+(h.yearSuffix||""));h.timeParse.forEach(function(a){h.addFormat(a,!0)});h.dateParse.forEach(function(a){h.addFormat(a)});return Sb[a]=h}function Wb(a,b,c,d){a.g.unshift({r:d,locale:a,q:q("^"+b+"$","i"),to:c})}function Yb(a){return a.slice(0,1).toUpperCase()+a.slice(1)}function Ub(a){return a.filter(function(a){return!!a}).join("|")}function cc(){var a=r.SugarNewDate;return a?a():new r}
+function dc(a,b){var c;if(G(a[0]))return a;if(y(a[0])&&!y(a[1]))return[a[0]];if(z(a[0])&&b)return[ec(a[0]),a[1]];c={};Nb.forEach(function(b,e){c[b.name]=a[e]});return[c]}function ec(a){var b,c={};if(a=a.match(/^(\d+)?\s?(\w+?)s?$/i))N(b)&&(b=parseInt(a[1])||1),c[a[2].toLowerCase()]=b;return c}function fc(a,b,c){var d;N(c)&&(c=Ob.length);for(b=b||0;b<c&&(d=Ob[b],!1!==a(d.name,d,b));b++);}
+function gc(a,b){var c={},d,e;b.forEach(function(b,f){d=a[f+1];N(d)||""===d||("year"===b&&(c.t=d.replace(/'/,"")),e=parseFloat(d.replace(/'/,"").replace(/,/,".")),c[b]=isNaN(e)?d.toLowerCase():e)});return c}function hc(a){a=a.trim().replace(/^just (?=now)|\.+$/i,"");return ic(a)}
+function ic(a){return a.replace(Mb,function(a,c,d){var e=0,g=1,f,h;if(c)return a;d.split("").reverse().forEach(function(a){a=Lb[a];var b=9<a;b?(f&&(e+=g),g*=a/(h||1),h=a):(!1===f&&(g*=10),e+=g*a);f=b});f&&(e+=g);return e})}
+function jc(a,b,c,d){function e(a){vb.push(a)}function g(){vb.forEach(function(a){a.call()})}function f(){var a=n.getWeekday();n.setWeekday(7*(k.num-1)+(a>Ba?Ba+7:Ba))}function h(){var a=B.i[k.edge];fc(function(a){if(M(k[a]))return E=a,!1},4);if("year"===E)k.e="month";else if("month"===E||"week"===E)k.e="day";n[(0>a.value?"endOf":"beginningOf")+Yb(E)]();-2===a.value&&n.reset()}function l(){var a;fc(function(b,c,d){"day"===b&&(b="date");if(M(k[b])){if(d>=wb)return n.setTime(NaN),!1;a=a||{};a[b]=k[b];
+delete k[b]}});a&&e(function(){n.set(a,!0)})}var n,x,ha,vb,B,k,E,wb,Ba,ra,ca;n=cc();vb=[];n.utc(d);C(a)?n.utc(a.isUTC()).setTime(a.getTime()):y(a)?n.setTime(a):G(a)?(n.set(a,!0),k=a):z(a)&&(ha=Y(b),a=hc(a),ha&&I(ha.o?[ha.o].concat(ha.g):ha.g,function(c,d){var g=a.match(d.q);if(g){B=d.locale;k=gc(g,d.to);B.o=d;k.utc&&n.utc();if(k.timestamp)return k=k.timestamp,!1;d.r&&(!z(k.month)&&(z(k.date)||Zb(ha,b)))&&(ca=k.month,k.month=k.date,k.date=ca);k.year&&2===k.t.length&&(k.year=100*R(U(cc(),"FullYear")/
+100)-100*R(k.year/100)+k.year);k.month&&(k.month=B.getMonth(k.month),k.shift&&!k.unit&&(k.unit=B.units[7]));k.weekday&&k.date?delete k.weekday:k.weekday&&(k.weekday=B.getWeekday(k.weekday),k.shift&&!k.unit&&(k.unit=B.units[5]));k.day&&(ca=B.i[k.day])?(k.day=ca.value,n.reset(),x=!0):k.day&&-1<(Ba=B.getWeekday(k.day))&&(delete k.day,k.num&&k.month?(e(f),k.day=1):k.weekday=Ba);k.date&&!y(k.date)&&(k.date=$b(B,k.date));k.ampm&&k.ampm===B.ampm[1]&&12>k.hour?k.hour+=12:k.ampm===B.ampm[0]&&12===k.hour&&
+(k.hour=0);if("offset_hours"in k||"offset_minutes"in k)n.utc(),k.offset_minutes=k.offset_minutes||0,k.offset_minutes+=60*k.offset_hours,"-"===k.offset_sign&&(k.offset_minutes*=-1),k.minute-=k.offset_minutes;k.unit&&(x=!0,ra=ac(B,k.num),wb=B.units.indexOf(k.unit)%8,E=W.units[wb],l(),k.shift&&(ra*=(ca=B.i[k.shift])?ca.value:0),k.sign&&(ca=B.i[k.sign])&&(ra*=ca.value),M(k.weekday)&&(n.set({weekday:k.weekday},!0),delete k.weekday),k[E]=(k[E]||0)+ra);k.edge&&e(h);"-"===k.year_sign&&(k.year*=-1);fc(function(a,
+b,c){b=k[a];var d=b%1;d&&(k[Ob[c-1].name]=R(d*("second"===a?1E3:60)),k[a]=Q(b))},1,4);return!1}}),k?x?n.advance(k):(n._utc&&n.reset(),kc(n,k,!0,!1,c)):("now"!==a&&(n=new r(a)),d&&n.addMinutes(-n.getTimezoneOffset())),g(),n.utc(!1));return{c:n,set:k}}function lc(a){var b,c=P(a),d=c,e=0;fc(function(a,f,h){b=Q(Da(c/f.b(),1));1<=b&&(d=b,e=h)},1);return[d,e,a]}
+function mc(a){var b=lc(a.millisecondsFromNow());if(6===b[1]||5===b[1]&&4===b[0]&&a.daysFromNow()>=cc().daysInMonth())b[0]=P(a.monthsFromNow()),b[1]=6;return b}function nc(a,b,c){function d(a,c){var d=U(a,"Month");return Y(c).months[d+12*b]}Z(a,d,c);Z(Yb(a),d,c,1)}function Z(a,b,c,d){X[a]=function(a,g){var f=b(a,g);c&&(f=f.slice(0,c));d&&(f=f.slice(0,d).toUpperCase()+f.slice(d));return f}}
+function oc(a,b,c){X[a]=b;X[a+a]=function(a,c){return T(b(a,c),2)};c&&(X[a+a+a]=function(a,c){return T(b(a,c),3)},X[a+a+a+a]=function(a,c){return T(b(a,c),4)})}function pc(a){var b=a.match(/(\{\w+\})|[^{}]+/g);Qb[a]=b.map(function(a){a.replace(/\{(\w+)\}/,function(b,e){a=X[e]||e;return e});return a})}
+function qc(a,b,c,d){var e;if(!a.isValid())return"Invalid Date";Date[b]?b=Date[b]:F(b)&&(e=mc(a),b=b.apply(a,e.concat(Y(d))));if(!b&&c)return e=e||mc(a),0===e[1]&&(e[1]=1,e[0]=1),a=Y(d),Xb(a,e,0<e[2]?"future":"past");b=b||"long";if("short"===b||"long"===b||"full"===b)b=Y(d)[b];Qb[b]||pc(b);var g,f;e="";b=Qb[b];g=0;for(c=b.length;g<c;g++)f=b[g],e+=F(f)?f(a,d):f;return e}
+function rc(a,b,c,d,e){var g,f,h,l=0,n=0,x=0;g=jc(b,c,null,e);0<d&&(n=x=d,f=!0);if(!g.c.isValid())return!1;if(g.set&&g.set.e){Rb.forEach(function(b){b.name===g.set.e&&(l=b.b(g.c,a-g.c)-1)});b=Yb(g.set.e);if(g.set.edge||g.set.shift)g.c["beginningOf"+b]();"month"===g.set.e&&(h=g.c.clone()["endOf"+b]().getTime());!f&&(g.set.sign&&"millisecond"!=g.set.e)&&(n=50,x=-50)}f=a.getTime();b=g.c.getTime();h=sc(a,b,h||b+l);return f>=b-n&&f<=h+x}
+function sc(a,b,c){b=new r(b);a=(new r(c)).utc(a.isUTC());23!==U(a,"Hours")&&(b=b.getTimezoneOffset(),a=a.getTimezoneOffset(),b!==a&&(c+=(a-b).minutes()));return c}
+function kc(a,b,c,d,e){function g(a){return M(b[a])?b[a]:b[a+"s"]}function f(a){return M(g(a))}var h;if(y(b)&&d)b={milliseconds:b};else if(y(b))return a.setTime(b),a;M(b.date)&&(b.day=b.date);fc(function(d,e,g){var l="day"===d;if(f(d)||l&&f("weekday"))return b.e=d,h=+g,!1;!c||("week"===d||l&&f("week"))||Sa(a,e.method,l?1:0)});Rb.forEach(function(c){var e=c.name;c=c.method;var h;h=g(e);N(h)||(d?("week"===e&&(h=(b.day||0)+7*h,c="Date"),h=h*d+U(a,c)):"month"===e&&f("day")&&Sa(a,"Date",15),Sa(a,c,h),
+d&&"month"===e&&(e=h,0>e&&(e=e%12+12),e%12!=U(a,"Month")&&Sa(a,"Date",0)))});d||(f("day")||!f("weekday"))||a.setWeekday(g("weekday"));var l;a:{switch(e){case -1:l=a>cc();break a;case 1:l=a<cc();break a}l=void 0}l&&fc(function(b,c){if((c.k||"week"===b&&f("weekday"))&&!(f(b)||"day"===b&&f("weekday")))return a[c.j](e),!1},h+1);return a}
+function Vb(a,b){var c=Kb,d={h:0,m:1,s:2},e;a=a||W;return c.replace(/{([a-z])}/g,function(c,f){var h=[],l="h"===f,n=l&&!b;if("t"===f)return a.ampm.join("|");l&&h.push(":");(e=a.timeSuffixes[d[f]])&&h.push(e+"\\s*");return 0===h.length?"":"(?:"+h.join("|")+")"+(n?"":"?")})}function tc(a,b,c){var d,e;y(a[1])?d=dc(a)[0]:(d=a[0],e=a[1]);return jc(d,e,b,c).c}
+H(r,!1,!0,{create:function(){return tc(arguments)},past:function(){return tc(arguments,-1)},future:function(){return tc(arguments,1)},addLocale:function(a,b){return bc(a,b)},setLocale:function(a){var b=Y(a,!1);Ib=b;a&&a!=b.code&&(b.code=a);return b},getLocale:function(a){return a?Y(a,!1):Ib},addFormat:function(a,b,c){Wb(Y(c),a,b)}});
+H(r,!0,!0,{set:function(){var a=dc(arguments);return kc(this,a[0],a[1])},setWeekday:function(a){if(!N(a))return Sa(this,"Date",U(this,"Date")+a-U(this,"Day"))},setISOWeek:function(a){var b=U(this,"Day")||7;if(!N(a))return this.set({month:0,date:4}),this.set({weekday:1}),1<a&&this.addWeeks(a-1),1!==b&&this.advance({days:b-1}),this.getTime()},getISOWeek:function(){var a;a=this.clone();var b=U(a,"Day")||7;a.addDays(4-b).reset();return 1+Q(a.daysSince(a.clone().beginningOfYear())/7)},beginningOfISOWeek:function(){var a=
+this.getDay();0===a?a=-6:1!==a&&(a=1);this.setWeekday(a);return this.reset()},endOfISOWeek:function(){0!==this.getDay()&&this.setWeekday(7);return this.endOfDay()},getUTCOffset:function(a){var b=this._utc?0:this.getTimezoneOffset(),c=!0===a?":":"";return!b&&a?"Z":T(Q(-b/60),2,!0)+c+T(P(b%60),2)},utc:function(a){oa(this,"_utc",!0===a||0===arguments.length);return this},isUTC:function(){return!!this._utc||0===this.getTimezoneOffset()},advance:function(){var a=dc(arguments,!0);return kc(this,a[0],a[1],
+1)},rewind:function(){var a=dc(arguments,!0);return kc(this,a[0],a[1],-1)},isValid:function(){return!isNaN(this.getTime())},isAfter:function(a,b){return this.getTime()>r.create(a).getTime()-(b||0)},isBefore:function(a,b){return this.getTime()<r.create(a).getTime()+(b||0)},isBetween:function(a,b,c){var d=this.getTime();a=r.create(a).getTime();var e=r.create(b).getTime();b=Ca(a,e);a=S(a,e);c=c||0;return b-c<d&&a+c>d},isLeapYear:function(){var a=U(this,"FullYear");return 0===a%4&&0!==a%100||0===a%400},
+daysInMonth:function(){return 32-U(new r(U(this,"FullYear"),U(this,"Month"),32),"Date")},format:function(a,b){return qc(this,a,!1,b)},relative:function(a,b){z(a)&&(b=a,a=null);return qc(this,a,!0,b)},is:function(a,b,c){var d,e;if(this.isValid()){if(z(a))switch(a=a.trim().toLowerCase(),e=this.clone().utc(c),!0){case "future"===a:return this.getTime()>cc().getTime();case "past"===a:return this.getTime()<cc().getTime();case "weekday"===a:return 0<U(e,"Day")&&6>U(e,"Day");case "weekend"===a:return 0===
+U(e,"Day")||6===U(e,"Day");case -1<(d=W.weekdays.indexOf(a)%7):return U(e,"Day")===d;case -1<(d=W.months.indexOf(a)%12):return U(e,"Month")===d}return rc(this,a,null,b,c)}},reset:function(a){var b={},c;a=a||"hours";"date"===a&&(a="days");c=Rb.some(function(b){return a===b.name||a===b.name+"s"});b[a]=a.match(/^days?/)?1:0;return c?this.set(b,!0):this},clone:function(){var a=new r(this.getTime());a.utc(!!this._utc);return a}});
+H(r,!0,!0,{iso:function(){return this.toISOString()},getWeekday:r.prototype.getDay,getUTCWeekday:r.prototype.getUTCDay});function uc(a,b){function c(){return R(this*b)}function d(){return tc(arguments)[a.j](this)}function e(){return tc(arguments)[a.j](-this)}var g=a.name,f={};f[g]=c;f[g+"s"]=c;f[g+"Before"]=e;f[g+"sBefore"]=e;f[g+"Ago"]=e;f[g+"sAgo"]=e;f[g+"After"]=d;f[g+"sAfter"]=d;f[g+"FromNow"]=d;f[g+"sFromNow"]=d;t.extend(f)}H(t,!0,!0,{duration:function(a){a=Y(a);return Xb(a,lc(this),"duration")}});
+W=Ib=r.addLocale("en",{plural:!0,timeMarker:"at",ampm:"am,pm",months:"January,February,March,April,May,June,July,August,September,October,November,December",weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",units:"millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s",numbers:"one,two,three,four,five,six,seven,eight,nine,ten",articles:"a,an,the",tokens:"the,st|nd|rd|th,of","short":"{Month} {d}, {yyyy}","long":"{Month} {d}, {yyyy} {h}:{mm}{tt}",full:"{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
+past:"{num} {unit} {sign}",future:"{num} {unit} {sign}",duration:"{num} {unit}",modifiers:[{name:"sign",src:"ago|before",value:-1},{name:"sign",src:"from now|after|from|in|later",value:1},{name:"edge",src:"last day",value:-2},{name:"edge",src:"end",value:-1},{name:"edge",src:"first day|beginning",value:1},{name:"shift",src:"last",value:-1},{name:"shift",src:"the|this",value:0},{name:"shift",src:"next",value:1}],dateParse:["{month} {year}","{shift} {unit=5-7}","{0?} {date}{1}","{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
+timeParse:"{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";")});Ob=Rb.concat().reverse();Nb=Rb.concat();Nb.splice(2,1);
+K(r,!0,!0,Rb,function(a,b,c){function d(a){a/=f;var c=a%1,d=b.error||0.999;c&&P(c%1)>d&&(a=R(a));return 0>a?Aa(a):Q(a)}var e=b.name,g=Yb(e),f=b.b(),h,l;b.j="add"+g+"s";h=function(a,b){return d(this.getTime()-r.create(a,b).getTime())};l=function(a,b){return d(r.create(a,b).getTime()-this.getTime())};a[e+"sAgo"]=l;a[e+"sUntil"]=l;a[e+"sSince"]=h;a[e+"sFromNow"]=h;a[b.j]=function(a,b){var c={};c[e]=a;return this.advance(c,b)};uc(b,f);3>c&&["Last","This","Next"].forEach(function(b){a["is"+b+g]=function(){return rc(this,
+b+" "+e,"en")}});4>c&&(a["beginningOf"+g]=function(){var a={};switch(e){case "year":a.year=U(this,"FullYear");break;case "month":a.month=U(this,"Month");break;case "day":a.day=U(this,"Date");break;case "week":a.weekday=0}return this.set(a,!0)},a["endOf"+g]=function(){var a={hours:23,minutes:59,seconds:59,milliseconds:999};switch(e){case "year":a.month=11;a.day=31;break;case "month":a.day=this.daysInMonth();break;case "week":a.weekday=6}return this.set(a,!0)})});
+W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?",!0,["year_sign","year","month","date"],!1,!0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?",!0,["date","month","year"],!0);W.addFormat("{full_month}[-.](\\d{4,4})",!1,["month","year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/",!1,["timestamp"]);W.addFormat(Vb(W),!1,Jb);Pb=W.g.slice(0,7).reverse();W.g=W.g.slice(7).concat(Pb);oc("f",function(a){return U(a,"Milliseconds")},!0);
+oc("s",function(a){return U(a,"Seconds")});oc("m",function(a){return U(a,"Minutes")});oc("h",function(a){return U(a,"Hours")%12||12});oc("H",function(a){return U(a,"Hours")});oc("d",function(a){return U(a,"Date")});oc("M",function(a){return U(a,"Month")+1});(function(){function a(a,c){var d=U(a,"Hours");return Y(c).ampm[Q(d/12)]||""}Z("t",a,1);Z("tt",a);Z("T",a,1,1);Z("TT",a,null,2)})();
+/* istanbul ignore next */
+(function(){function a(a,c){var d=U(a,"Day");return Y(c).weekdays[d]}Z("dow",a,3);Z("Dow",a,3,1);Z("weekday",a);Z("Weekday",a,null,1)})();nc("mon",0,3);nc("month",0);nc("month2",1);nc("month3",2);X.ms=X.f;X.milliseconds=X.f;X.seconds=X.s;X.minutes=X.m;X.hours=X.h;X["24hr"]=X.H;X["12hr"]=X.h;X.date=X.d;X.day=X.d;X.year=X.yyyy;K(r,!0,!0,"short,long,full",function(a,b){a[b]=function(a){return qc(this,b,!1,a)}});
+"\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07".split("").forEach(function(a,b){9<b&&(b=za(10,b-9));Lb[a]=b});xa(Lb,Ka);Mb=q("([\u671f\u9031\u5468])?([\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07"+Ja+"]+)(?!\u6628)","g");
+/* istanbul ignore next */
+(function(){var a=W.weekdays.slice(0,7),b=W.months.slice(0,12);K(r,!0,!0,"today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b),function(a,b){a["is"+Yb(b)]=function(a){return this.is(b,0,a)}})})();r.utc||(r.utc={create:function(){return tc(arguments,0,!0)},past:function(){return tc(arguments,-1,!0)},future:function(){return tc(arguments,1,!0)}});
+H(r,!1,!0,{RFC1123:"{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}",RFC1036:"{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}",ISO8601_DATE:"{yyyy}-{MM}-{dd}",ISO8601_DATETIME:"{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}"});})();
diff --git a/src/util/colorFile.js b/src/util/colorFile.js
new file mode 100755
index 0000000..73c063e
--- /dev/null
+++ b/src/util/colorFile.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const strip = require('./stripAnsi');
+
+const chalk = {};
+const map = {cyan: 36, red: 31, magenta: 35};
+Object.keys(map).forEach(function (key, value) {
+  chalk[key] = function (str) {
+    return `\u001b[${value}m${str}\u001b[39m`;
+  };
+});
+
+/**
+ * Wraps file strings in ANSI colors
+ * based on their extension.
+ *
+ * @param {file} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (file) {
+  const audio = ['aac', 'au', 'flac', 'mid', 'midi', 'mka', 'mp3', 'mpc', 'ogg', 'ra', 'wav', 'axa', 'oga', 'spx', 'xspf'];
+  const archive = ['tar', 'tgz', 'arj', 'taz', 'lzh', 'lzma', 'tlz', 'txz', 'zip', 'z', 'Z', 'dz', 'gz', 'lz', 'xz', 'bz2', 'bz', 'tbz', 'tbz2', 'tz', 'deb', 'rpm', 'jar', 'rar', 'ace', 'zoo', 'cpio', '7z', 'rz'];
+  const images = ['jpg', 'jpeg', 'gif', 'bmp', 'pbm', 'pgm', 'ppm', 'tga', 'xbm', 'xpm', 'tif', 'tiff', 'png', 'svg', 'svgz', 'mng', 'pcx', 'mov', 'mpg', 'mpeg', 'm2v', 'mkv', 'ogm', 'mp4', 'm4v', 'mp4v', 'vob', 'qt', 'nuv', 'wmv', 'asf', 'rm', 'rmvb', 'flc', 'avi', 'fli', 'flv', 'gl', 'dl', 'xcf', 'xwd', 'yuv', 'cgm', 'emf', 'axv', 'anx', 'ogv', 'ogx'];
+
+  let extension = String(file).toLowerCase().trim().split('.');
+  extension = extension[extension.length - 1];
+
+  let colored = strip(file);
+  colored = (audio.indexOf(extension) > -1) ? chalk.cyan(file) :
+    (archive.indexOf(extension) > -1) ? chalk.red(file) :
+    (images.indexOf(extension) > -1) ? chalk.magenta(file) :
+    colored;
+
+  return colored;
+};
diff --git a/src/util/columnify.js b/src/util/columnify.js
new file mode 100755
index 0000000..c6821c2
--- /dev/null
+++ b/src/util/columnify.js
@@ -0,0 +1,60 @@
+'use strict';
+
+const strip = require('./stripAnsi');
+const pad = require('./pad');
+
+/**
+ * Formats an array to display in a TTY
+ * in a pretty fashion.
+ *
+ * @param {Array} arr
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (arr, options) {
+  arr = arr || [];
+  options = options || {};
+  const bk = JSON.parse(JSON.stringify(arr));
+  const width = (options.width && !isNaN(options.width)) ?
+    options.width :
+    process.stdout.columns;
+  const longest = strip(bk.sort(function (a, b) {
+    return strip(b).length - strip(a).length;
+  })[0] || '').length + 2;
+  const fullWidth = strip(arr.join('')).length;
+  const fitsOneLine = ((fullWidth + (arr.length * 2)) <= width);
+  let cols = Math.floor(width / longest);
+  cols = (cols < 1) ? 1 : cols;
+  if (fitsOneLine) {
+    return arr.join('  ');
+  }
+  let col = 0;
+  const lines = [];
+  let line = '';
+  for (let i = 0; i < arr.length; ++i) {
+    if (col < cols) {
+      col++;
+    } else {
+      if (String(strip(line)).trim() !== '') {
+        lines.push(line);
+      }
+      line = '';
+      col = 1;
+    }
+    if (cols === 1) {
+      // If we have files so damn
+      // long that we wrap, don't pad
+      // the lines.
+      line += arr[i];
+    } else {
+      // Pad the lines based on the
+      // longest word.
+      line += pad(arr[i], longest, ' ');
+    }
+  }
+  if (line !== '') {
+    lines.push(line);
+  }
+  return lines.join('\n');
+};
diff --git a/src/util/converter.date.js b/src/util/converter.date.js
new file mode 100755
index 0000000..1bbb98d
--- /dev/null
+++ b/src/util/converter.date.js
@@ -0,0 +1,31 @@
+'use strict';
+
+/**
+ * Date conversion utilities
+ */
+
+const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(num, padding) {
+  padding = padding || '0';
+  num = parseFloat(num);
+  if (num < 10) {
+    return `${padding}${num}`;
+  }
+  return num;
+}
+
+module.exports = {
+
+  unix(dt) {
+    let date = dt;
+    let day = pad(date.getDate(), ' ');
+    const month = months[date.getMonth()];
+    const hour = pad(date.getHours());
+    const min = pad(date.getMinutes());
+    const hourMin = `${hour}:${min}`;
+    day = (day.length === 1) ? (` ${day}`) : day;
+    date = `${month} ${day} ${hourMin}`;
+    return date;
+  }
+};
diff --git a/src/util/converter.path.js b/src/util/converter.path.js
new file mode 100755
index 0000000..dd6547e
--- /dev/null
+++ b/src/util/converter.path.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const path = require('path');
+
+/**
+ * Path conversion utilities
+ */
+
+module.exports = {
+
+  unix(str) {
+    let input = path.normalize(str);
+    input = input.replace(/\\/g, '\/');
+    const parts = input.split(':');
+    const drive = parts.shift();
+    const isLetter = (drive.length === 1 && drive.match(/[a-z]/i));
+    const result = (isLetter) ? drive + parts.join(':') : input;
+    return result;
+  }
+};
diff --git a/src/util/converter.permissions.js b/src/util/converter.permissions.js
new file mode 100755
index 0000000..f1f44e7
--- /dev/null
+++ b/src/util/converter.permissions.js
@@ -0,0 +1,41 @@
+'use strict';
+
+/**
+ * Permission conversion utilities
+ */
+
+module.exports = {
+
+  listing: {
+    0: '---',
+    1: '--x',
+    2: '-w-',
+    3: '-wx',
+    4: 'r--',
+    5: 'r-x',
+    6: 'rw-',
+    7: 'rwx'
+  },
+
+  modeToRWX(mode) {
+    const octal = this.modeToOctal(mode);
+    const rwx = this.octalToRWX(octal);
+    return rwx;
+  },
+
+  modeToOctal(mode) {
+    const octal = `0${(mode & 0o777).toString(8)}`;
+    return octal;
+  },
+
+  octalToRWX(octal) {
+    if (!octal) {
+      return undefined;
+    }
+    const list = this.listing;
+    const a = list[String(octal).charAt(1)];
+    const b = list[String(octal).charAt(2)];
+    const c = list[String(octal).charAt(3)];
+    return a + b + c;
+  }
+};
diff --git a/src/util/expand.js b/src/util/expand.js
new file mode 100755
index 0000000..83d469a
--- /dev/null
+++ b/src/util/expand.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+  const total = list.length;
+  const files = [];
+  if (list.length < 1) {
+    return [];
+  }
+  for (let i = 0; i < total; ++i) {
+    const res = glob.sync(list[i], {});
+    files[i] = (res.length > 0) ?
+      res :
+      list[i];
+  }
+  let out = [];
+  for (let i = 0; i < files.length; ++i) {
+    out = (Array.isArray(files[i])) ?
+      out.concat(files[i]) :
+      out.concat([files[i]]);
+  }
+  return out;
+};
diff --git a/src/util/fetch.js b/src/util/fetch.js
new file mode 100755
index 0000000..c21e080
--- /dev/null
+++ b/src/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+const expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+  files = files || [];
+  stdin = (stdin !== undefined) ? stdin : [];
+  const f = expand(files);
+
+  if (!(f.length === 0 && files.length > 0)) {
+    files = f;
+  }
+
+  for (let i = 0; i < files.length; ++i) {
+    try {
+      const stat = fs.statSync(files[i]);
+      if (stat.isDirectory()) {
+        files[i] = options.onDirectory(files[i]);
+      } else {
+        files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+      }
+    } catch (e) {
+      files[i] = options.onInvalidFile(files[i]);
+    }
+  }
+
+  const agg = (files.length < 1) ? stdin : files;
+  const final = [];
+
+  for (let i = 0; i < agg.length; ++i) {
+    if (agg[i] !== undefined) {
+      final.push(agg[i]);
+    }
+  }
+  return final;
+};
diff --git a/src/util/fileFromPath.js b/src/util/fileFromPath.js
new file mode 100755
index 0000000..ed0da5a
--- /dev/null
+++ b/src/util/fileFromPath.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * Parses a path and returns just the file
+ *
+ * @param {path} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (path) {
+  let fileShort = String(path).split('/');
+  fileShort = fileShort[fileShort.length - 1];
+  fileShort = fileShort.split('\\');
+  fileShort = fileShort[fileShort.length - 1];
+  return fileShort;
+};
diff --git a/src/util/intercept.js b/src/util/intercept.js
new file mode 100755
index 0000000..5cb76e2
--- /dev/null
+++ b/src/util/intercept.js
@@ -0,0 +1,47 @@
+'use strict';
+
+const _ = require('lodash');
+
+/**
+ * Intercepts stdout, passes thru callback
+ * also pass console.error thru stdout so it goes to callback too
+ * (stdout.write and stderr.write are both refs to the same stream.write function)
+ * returns an unhook() function, call when done intercepting
+ *
+ * @param {Function} callback
+ * @return {Function}
+ */
+
+module.exports = function (callback) {
+  const oldStdoutWrite = process.stdout.write;
+  const oldConsoleError = console.error;
+  process.stdout.write = (function (write) {
+    return function (string) {
+      const args = _.toArray(arguments);
+      args[0] = interceptor(string);
+      write.apply(process.stdout, args);
+    };
+  }(process.stdout.write));
+
+  console.error = (function () {
+    return function () {
+      const args = _.toArray(arguments);
+      args.unshift('\x1b[31m[ERROR]\x1b[0m');
+      console.log.apply(console.log, args);
+    };
+  }(console.error));
+
+  function interceptor(string) {
+    // only intercept the string
+    const result = callback(string);
+    if (typeof result === 'string') {
+      string = result.replace(/\n$/, '') + (result && (/\n$/).test(string) ? '\n' : '');
+    }
+    return string;
+  }
+  // puts back to original
+  return function unhook() {
+    process.stdout.write = oldStdoutWrite;
+    console.error = oldConsoleError;
+  };
+};
diff --git a/src/util/interfacer.js b/src/util/interfacer.js
new file mode 100755
index 0000000..527c08b
--- /dev/null
+++ b/src/util/interfacer.js
@@ -0,0 +1,43 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+  const self = this;
+  let stdout = '';
+  opt.options = opt.options || {};
+  opt.callback = opt.callback || function () {};
+  opt.command = opt.command || {exec() {}};
+
+  const logger = {
+    log(out) {
+      stdout += `${out}\n`;
+      if (opt.silent !== true) {
+        // process.stdout.write(out) // to do - handle newline problem.
+        self.log(out);
+      }
+    }
+  };
+
+  function onResult(result) {
+    result = (result === undefined) ? 0 : result;
+    opt.callback(null, stdout);
+    return stdout;
+  }
+
+  if (opt.async === true) {
+    return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+  }
+  return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
diff --git a/src/util/lpad.js b/src/util/lpad.js
new file mode 100755
index 0000000..4b09230
--- /dev/null
+++ b/src/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  const len = Math.max(0, width - strip(str).length);
+  return Array(len + 1).join(delimiter) + str;
+};
diff --git a/src/util/pad.js b/src/util/pad.js
new file mode 100755
index 0000000..c6fc995
--- /dev/null
+++ b/src/util/pad.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const strip = require('./stripAnsi');
+
+/**
+ * Pads a value with with space or
+ * a specified delimiter to match a
+ * given width.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+  width = Math.floor(width);
+  delimiter = delimiter || ' ';
+  const len = Math.max(0, width - strip(str).length);
+  return str + Array(len + 1).join(delimiter);
+};
diff --git a/src/util/stripAnsi.js b/src/util/stripAnsi.js
new file mode 100755
index 0000000..7eedbcb
--- /dev/null
+++ b/src/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+  const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+  return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
diff --git a/src/util/unlinkSync.js b/src/util/unlinkSync.js
new file mode 100755
index 0000000..fe37f34
--- /dev/null
+++ b/src/util/unlinkSync.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const fs = require('fs');
+
+/**
+ * Normalizes _unlinkSync() across
+ * platforms to match Unix behavior, i.e.
+ * file can be unlinked even its it's
+ * read only.
+ * See https://github.com/joyent/node/issues/3006
+ *
+ * @param {String} file
+ * @api public
+ */
+
+module.exports = function (file) {
+  try {
+    fs.unlinkSync(file);
+  } catch (e) {
+    // Try to override file permission
+    /* istanbul ignore if */
+    if (e.code === 'EPERM') {
+      fs.chmodSync(file, '0666');
+      fs.unlinkSync(file);
+    } else {
+      /* istanbul ignore next */
+      throw e;
+    }
+  }
+};
diff --git a/src/util/walkDir.js b/src/util/walkDir.js
new file mode 100755
index 0000000..1b74e62
--- /dev/null
+++ b/src/util/walkDir.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * Walks a single directory calling
+ * a callback function for each file or
+ * folder, returning the path and results
+ * of fs.statSync.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  function readFile(path, cbk) {
+    let stat;
+    try {
+      stat = fs.statSync(path);
+      if (stat.isFile() || stat.isDirectory()) {
+        cbk(path, stat);
+      }
+    } catch (e) {
+      // .. if we can't read the file, forget
+      // about it for now.
+    }
+  }
+  try {
+    const dirs = fs.readdirSync(currentDirPath);
+    dirs.forEach(function (name) {
+      const filePath = path.join(currentDirPath, name);
+      readFile(filePath, callback);
+    });
+  } catch (e) {
+    if (e.code === 'ENOTDIR') {
+      readFile(currentDirPath, callback);
+    }
+  }
+};
diff --git a/src/util/walkDirRecursive.js b/src/util/walkDirRecursive.js
new file mode 100755
index 0000000..06d7113
--- /dev/null
+++ b/src/util/walkDirRecursive.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * Recursively walks through and executes
+ * a callback function for each directory found.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+  fs.readdirSync(currentDirPath).forEach(function (name) {
+    const filePath = path.join(currentDirPath, name);
+    const stat = fs.statSync(filePath);
+    if (stat.isDirectory()) {
+      callback(filePath, stat);
+      module.exports(filePath, callback);
+    }
+  });
+};
diff --git a/src/windows.js b/src/windows.js
new file mode 100755
index 0000000..4a633aa
--- /dev/null
+++ b/src/windows.js
@@ -0,0 +1,124 @@
+'use strict';
+
+const _ = require('lodash');
+const os = require('os');
+
+const commands = require('./../commands.json').windowsCommands;
+
+module.exports = {
+
+  registerCommands(self) {
+    self.vorpal
+      .catch('[words...]', 'Catches content')
+      .parse(function (input) {
+        // Look for aliases and translate them.
+        // Makes cash.alias and cash.unalias work.
+        const parts = String(input).split(' ');
+        const first = parts.shift();
+        let out = input;
+        const translation = self.vorpal._aliases[first];
+        if (self.vorpal._aliases && translation) {
+          /* istanbul ignore next */
+          out = `${translation} ${parts.join(' ')}`;
+        }
+        return out;
+      })
+      /* istanbul ignore next */
+      .autocomplete(function () {
+        /* istanbul ignore next */
+        return _.map(self.vorpal.commands, '_name');
+      })
+      .action(function (args, cb) {
+        cb = cb || function () {};
+        const spawn = require('child_process').spawn;
+        const slf = this;
+
+        const words = args.words.join(' ');
+        let argus;
+
+        let cmd;
+        // Only register commands if on Windows.
+        /* istanbul ignore next */
+        if (os.platform() === 'win32') {
+          for (let i = 0; i < commands.length; ++i) {
+            if (String(words.slice(0, commands[i].length)).toLowerCase() === commands[i].toLowerCase()) {
+              cmd = commands[i];
+              argus = String(words.slice(commands[i].length, words.length)).trim().split(' ');
+              argus = (argus.length === 1 && argus[0] === '') ? [] : argus;
+            }
+          }
+        }
+
+        // Accommodate tests for Linux.
+        if (words === 'cash-test') {
+          cmd = 'echo';
+          argus = ['hi'];
+        }
+
+        if (cmd === undefined || argus === undefined) {
+          slf.help();
+          cb();
+          return;
+        }
+
+        argus.unshift(cmd);
+        argus.unshift('/C');
+        let proc;
+        let out = '';
+        try {
+          proc = spawn('cmd', argus);
+        } catch (e) {
+          /* istanbul ignore next */
+          slf.log(e);
+        }
+
+        let closed = false;
+
+        // Properly print stdout as it's fed,
+        // waiting for line breaks before sending
+        // it to Vorpal.
+        function print() {
+          const parts = String(out).split('\n');
+          /* istanbul ignore next */
+          if (parts.length > 1) {
+            out = parts.pop();
+            const logging = String(parts.join('\n')).replace(/\r\r/g, '\r');
+            slf.log(logging);
+          }
+          /* istanbul ignore next */
+          if (closed === false) {
+            setTimeout(function () {
+              print();
+            }, 50);
+          }
+        }
+        print();
+
+        /* istanbul ignore next */
+        proc.stdout.on('data', function (data) {
+          out += data.toString('utf8');
+        });
+
+        /* istanbul ignore next */
+        proc.stderr.on('data', function (data) {
+          out += data.toString('utf8');
+        });
+
+        proc.on('close', function () {
+          closed = true;
+          if (String(out).trim() !== '') {
+            slf.log(String(out).replace(/\r\r/g, '\r'));
+            out = '';
+          }
+          /* istanbul ignore next */
+          setTimeout(function () {
+            cb();
+          }, 150);
+        });
+
+        proc.on('error', function (data) {
+          out += data.toString('utf8');
+        });
+      });
+  }
+};
diff --git a/test/alias.js b/test/alias.js
new file mode 100755
index 0000000..2fb4c8d
--- /dev/null
+++ b/test/alias.js
@@ -0,0 +1,85 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+
+// Cleans all alias junk out of
+// localStorage.
+function clear() {
+  cash._aliases = {};
+  const ls = cash.vorpal.localStorage._localStorage;
+  cash.vorpal.localStorage.removeItem('aliases');
+  ls.keys = ls.keys.filter(function (key) {
+    if (String(key).indexOf('alias|') > -1) {
+      delete ls.metaKeyMap[key];
+      return false;
+    }
+  });
+}
+
+describe('alias', function () {
+  before(function () {
+    clear();
+  });
+
+  after(function () {
+    clear();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.alias);
+  });
+
+  it('should create an alias with an equal symbol', function () {
+    (function () {
+      cash.alias('foo=bar');
+    }).should.not.throw();
+    cash.alias('foo').should.equal('alias foo=\'bar\'\n');
+  });
+
+  it('should print msg when reading an invalid alias', function () {
+    cash.alias('lalalala').should.equal('-cash: alias: lalalala: not found\n');
+  });
+
+  it('should rename an alias', function () {
+    (function () {
+      cash.alias('foo=cows');
+    }).should.not.throw();
+    cash.alias('foo').should.equal('alias foo=\'cows\'\n');
+  });
+
+  it('should create an alias with spaces and multiple words', function () {
+    (function () {
+      cash.alias('foo bar tender nice to meet you');
+    }).should.not.throw();
+    cash.alias('foo').should.equal('alias foo=\'bar tender nice to meet you\'\n');
+  });
+
+  it('should deal with surrounding quotes', function () {
+    cash.alias('foo "bar tender nice to meet you"');
+    cash.alias('foo').should.equal('alias foo=\'bar tender nice to meet you\'\n');
+    cash.alias('foo=\'bar tender nice to meet you\'');
+    cash.alias('foo').should.equal('alias foo=\'bar tender nice to meet you\'\n');
+  });
+
+  it('should handle multiple aliases', function () {
+    clear();
+    cash.alias('a "a"');
+    cash.alias('b "b"');
+    cash.alias('c "c"');
+    cash.alias('a').should.equal('alias a=\'a\'\n');
+    cash.alias('b').should.equal('alias b=\'b\'\n');
+    cash.alias('c').should.equal('alias c=\'c\'\n');
+  });
+
+  it('should list all registered aliases', function () {
+    cash.alias().should.equal('alias a=\'a\'\nalias b=\'b\'\nalias c=\'c\'\n');
+  });
+
+  describe('-p', function () {
+    it('should list all registered aliases', function () {
+      cash.alias(undefined, {p: true}).should.equal('alias a=\'a\'\nalias b=\'b\'\nalias c=\'c\'\n');
+    });
+  });
+});
diff --git a/test/cat.js b/test/cat.js
new file mode 100755
index 0000000..1242e4e
--- /dev/null
+++ b/test/cat.js
@@ -0,0 +1,127 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+require('shelljs/global');
+
+describe('cat', function () {
+  before(function () {
+    'aardvark'.to('a.test');
+    'batman'.to('b.test');
+    'dont\n\n\neat\naardvarks\n\n\n'.to('c.test2');
+  });
+
+  after(function () {
+    $.rm(['a.test', 'b.test', 'c.test2']);
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.cat);
+  });
+
+  it('should do nothing when called by itself', function () {
+    const results = cash.cat();
+    results.should.equal('');
+  });
+
+  it('should spit back a single file', function () {
+    const results = cash.cat('a.test');
+    results.should.equal('aardvark\n');
+  });
+
+  // The line breaks here don't technically conform
+  // to cat, but Vorpal spits a linebreak after every
+  // log, and this is a deeper, broader problem
+  // that needs consideration.
+  it('should spit multiple files', function () {
+    const results = cash.cat(['a.test', 'b.test']);
+    results.should.equal('aardvark\nbatman\n');
+  });
+
+  it('should accept wildcards and regex', function () {
+    const results = cash.cat(['*.test']);
+    results.should.equal('aardvark\nbatman\n');
+  });
+
+  describe('cat -b', function () {
+    it('should number non-blank lines', function () {
+      const results = cash.cat('c.test2', {numbernonblank: true});
+      results.should.equal('     1  dont\n\n\n     2  eat\n     3  aardvarks\n\n\n');
+    });
+  });
+
+  describe('cat -E', function () {
+    it('should show $ at the end of each line', function () {
+      const results = cash.cat('c.test2', {showends: true});
+      results.should.equal('dont$\n$\n$\neat$\naardvarks$\n$\n$\n');
+    });
+  });
+
+  describe('cat -n', function () {
+    it('should number each line', function () {
+      const results = cash.cat('c.test2', {number: true});
+      results.should.equal('     1  dont\n     2  \n     3  \n     4  eat\n     5  aardvarks\n     6  \n     7  \n');
+    });
+  });
+
+  describe('cat -s', function () {
+    it('should supress repeated empty output lines', function () {
+      const results = cash.cat('c.test2', {squeezeblank: true});
+      results.should.equal('dont\n\neat\naardvarks\n\n');
+    });
+  });
+
+  describe('cat -T', function () {
+    it('should show tab characters as ^I', function () {
+      // This is stupid, but I have to Volkswagon
+      // this one. My text editor automatically converts
+      // tabs to spaces, so I can't write a tab character.
+      // But it works: I promise.
+      true.should.be.true;
+    });
+  });
+
+  // This is not yet implemented - I need help
+  // with this one from someone who understands
+  // character encoding better than I do...
+  describe.skip('cat -v', function () {
+    it('should use ^ and M- notation, except for LFD and TAB', function () {
+      true.should.be.true;
+    });
+  });
+
+  describe('cat -A', function () {
+    it('should be equivalent to -vET', function () {
+      const results = cash.cat('c.test2', {showall: true});
+      results.should.equal('dont$\n$\n$\neat$\naardvarks$\n$\n$\n');
+    });
+  });
+
+  describe('cat -e', function () {
+    it('should be equivalent to -vE', function () {
+      const results = cash.cat('c.test2', {e: true});
+      results.should.equal('dont$\n$\n$\neat$\naardvarks$\n$\n$\n');
+    });
+  });
+
+  describe('cat -t', function () {
+    it('should be equivalent to -vT', function () {
+      const results = cash.cat('c.test2', {t: true});
+      results.should.equal('dont\n\n\neat\naardvarks\n\n\n');
+    });
+  });
+
+  describe('programmatic use', function () {
+    it('should execute in vorpal mode sync', function () {
+      const result = cash('cat a.test');
+      result.should.equal('aardvark\n');
+    });
+
+    it('should handle strings and arrays gracefully', function () {
+      cash.cat('a.test').should.equal('aardvark\n');
+      cash.cat(['a.test']).should.equal('aardvark\n');
+    });
+  });
+});
diff --git a/test/cd.js b/test/cd.js
new file mode 100755
index 0000000..973a47d
--- /dev/null
+++ b/test/cd.js
@@ -0,0 +1,51 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const util = require('./util/util');
+const pathConverter = require('../dist/util/converter.path.js');
+const delimiter = require('../dist/delimiter');
+
+describe('cd', function () {
+  before(function (done) {
+    util.writeSampleDir(function () {
+      process.chdir('./testing/');
+      done();
+    });
+  });
+
+  after(function () {
+    process.chdir('..');
+    util.deleteSampleDir();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.cd);
+  });
+
+  it('should traverse a sub directory', function () {
+    cash.cd('./sub');
+    String(pathConverter.unix(process.cwd())).should.containEql('/testing');
+  });
+
+  it('should go up a directory', function () {
+    cash.cd('..');
+    String(pathConverter.unix(process.cwd())).should.not.containEql('/sub');
+    String(pathConverter.unix(process.cwd())).should.containEql('/testing');
+  });
+
+  it('should go to the home dir if nothing is passed', function () {
+    const current = process.cwd();
+    cash.cd('');
+    String(pathConverter.unix(process.cwd())).should.not.containEql('/cash');
+    String(pathConverter.unix(process.cwd())).should.containEql(pathConverter.unix(delimiter.getHomeDir()));
+    process.chdir(current);
+    String(pathConverter.unix(process.cwd())).should.containEql('/cash');
+  });
+
+  it('should reject bs directories', function () {
+    const result = cash.cd('fubar');
+    result.should.equal('-bash: cd: fubar: No such file or directory\n');
+  });
+});
diff --git a/test/cp.js b/test/cp.js
new file mode 100755
index 0000000..de3fd2c
--- /dev/null
+++ b/test/cp.js
@@ -0,0 +1,127 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+
+function burninate() {
+  $.rm('-rf', './cptemp');
+  $.rm('-rf', 'cp-a');
+  $.rm('-rf', 'cp-b');
+  $.rm('-rf', 'cp-c');
+  $.rm('-rf', 'cp-d');
+  $.rm('-rf', 'cp-e');
+  $.rm('-rf', 'cpra');
+  $.rm('-rf', 'cprb');
+}
+
+function reset() {
+  burninate();
+  $.mkdir('-p', 'cpra/cpra2/cpra3/cpra4');
+  $.touch('cpra/cpra2/cpra3/cpra4/cprfile.file');
+  $.mkdir('cprb');
+  $.mkdir('cptemp');
+  $.touch('cp-a');
+  $.touch('cp-b');
+  $.touch('cp-c');
+}
+
+describe('cp', function () {
+  before(function () {
+    burninate();
+  });
+
+  after(function () {
+    burninate();
+  });
+
+  beforeEach(function () {
+    reset();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.cp);
+  });
+
+  it('should show usage when not passed anything', function () {
+    const usage = 'cp: missing file operand\nTry \'cp --help\' for more information.\n';
+    cash.cp().should.equal(usage);
+    cash.cp('').should.equal(usage);
+    cash.cp([]).should.equal(usage);
+  });
+
+  it('should show usage when passed only one param', function () {
+    const usage = 'cp: missing destination file operand after foo\nTry \'cp --help\' for more information.\n';
+    cash.cp('foo').should.equal(usage);
+    cash.cp(['foo']).should.equal(usage);
+  });
+
+  it('should copy a file', function () {
+    cash.cp('cp-a cptemp/cp-a');
+    $.test('-e', './cptemp/cp-a').should.equal(true);
+    $.test('-e', 'cp-a').should.equal(true);
+  });
+
+  it('should move multiple files', function () {
+    cash.cp('cp-a cp-b cptemp');
+    $.test('-e', 'cp-a').should.equal(true);
+    $.test('-e', 'cp-b').should.equal(true);
+    $.test('-e', './cptemp/cp-a').should.equal(true);
+    $.test('-e', './cptemp/cp-b').should.equal(true);
+  });
+
+  it('should only accept directories on multiple files', function () {
+    cash.cp('cp-a cp-b cptemp/cp-cows').should
+      .equal('cp: target cptemp/cp-cows is not a directory\n');
+  });
+
+  it('should skip and give message on non-existing src files', function () {
+    const msg =
+      'cp: cannot stat cp-vorpal: No such file or directory\n' +
+      'cp: cannot stat cp-howdy: No such file or directory\n';
+    cash.cp('cp-a cp-b cp-vorpal cp-c cp-howdy cptemp').should
+      .equal(msg);
+    $.test('-e', 'cp-a').should.equal(true);
+    $.test('-e', 'cp-vorpal').should.equal(false);
+    $.test('-e', './cptemp/cp-a').should.equal(true);
+    $.test('-e', './cptemp/cp-b').should.equal(true);
+    $.test('-e', './cptemp/cp-c').should.equal(true);
+  });
+
+  it('should clobber existing files', function () {
+    'foxes'.to('cp-d');
+    'elephants'.to('cp-e');
+    cash.cp('cp-d cp-e');
+    $.test('-e', 'cp-d').should.equal(true);
+    $.cat('cp-e').should.equal('foxes');
+  });
+
+  describe('-n', function () {
+    it('should not clobber existing files', function () {
+      'foxes'.to('cp-d');
+      'elephants'.to('cp-e');
+      cash.cp('cp-d cp-e', {noclobber: true}).should.equal('');
+      $.test('-e', 'cp-d').should.equal(true);
+      $.cat('cp-d').should.equal('foxes');
+      $.cat('cp-e').should.equal('elephants');
+    });
+  });
+
+  describe('-f', function () {
+    it('should overwrite -n', function () {
+      'foxes'.to('cp-d');
+      'elephants'.to('cp-e');
+      cash.cp('cp-d cp-e', {noclobber: true, force: true});
+      $.test('-e', 'cp-d').should.equal(true);
+      $.cat('cp-e').should.equal('foxes');
+    });
+  });
+
+  describe('-r', function () {
+    it('should copy a file recursively', function () {
+      cash.cp('cpra cprb', {recursive: true}).should.equal('');
+      $.test('-e', 'cpra/cpra2/cpra3/cpra4/cprfile.file').should.equal(true);
+    });
+  });
+});
diff --git a/test/echo.js b/test/echo.js
new file mode 100755
index 0000000..2458420
--- /dev/null
+++ b/test/echo.js
@@ -0,0 +1,70 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+
+describe('echo', function () {
+  before(function (done) {
+    done();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.echo);
+  });
+
+  it('should echo back a single word', function () {
+    const results = cash.echo('hi');
+    results.should.equal('hi\n');
+  });
+
+  it('should echo back multiple words', function () {
+    const results = cash.echo('hi my name is slim shady');
+    results.should.equal('hi my name is slim shady\n');
+  });
+
+  it('should echo back dirty input', function () {
+    const fixture = 'hi! --help me i\'m @#$@# angry and r@ndom! "" 0 ';
+    const results = cash.echo(fixture);
+    results.should.equal(`${fixture}\n`);
+  });
+
+  describe('echo -e', function () {
+    it('should interpret backspace with \\b', function () {
+      const results = cash.echo('this  \\bone sentences\\b should be grammm\\batically correct.', {e: true});
+      results.should.equal('this one sentence should be grammatically correct.\n');
+    });
+
+    it('should produce no further output with \\c', function () {
+      const results = cash.echo('don\'t do drugs\\c, kid.', {e: true});
+      results.should.equal('don\'t do drugs\n');
+    });
+
+    it('should interpret a newline with \\n', function () {
+      const results = cash.echo('these\\nare\\non\\ndifferent\\nlines.', {e: true});
+      results.should.equal('these\nare\non\ndifferent\nlines.\n');
+    });
+
+    it('should interpret a carriage return with \\r', function () {
+      const results = cash.echo('these\\rare\\ron\\rdifferent\\rlines.', {e: true});
+      results.should.equal('these\rare\ron\rdifferent\rlines.\n');
+    });
+
+    it('should interpret a tab with \\t', function () {
+      const results = cash.echo('tab\\tme.', {e: true});
+      results.should.equal('tab     me.\n');
+    });
+
+    it('should carriage return with \\r', function () {
+      const results = cash.echo('these\\rare\\ron\\rdifferent\\rlines.', {e: true});
+      results.should.equal('these\rare\ron\rdifferent\rlines.\n');
+    });
+  });
+
+  describe('echo -E', function () {
+    it('should explicitly suppress backslash interpretations', function () {
+      const results = cash.echo('the \\cquick \\nbrown \\rfox \\tjumped \\\\over', {e: true, E: true});
+      results.should.equal('the \\cquick \\nbrown \\rfox \\tjumped \\\\over\n');
+    });
+  });
+});
diff --git a/test/help.js b/test/help.js
new file mode 100755
index 0000000..8e4a9d0
--- /dev/null
+++ b/test/help.js
@@ -0,0 +1,23 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const os = require('os');
+
+describe('help', function () {
+  it('should exist', function () {
+    should.exist(cash);
+  });
+
+  // Appveyor creates some problems
+  // that I can't reproduce on any Windows
+  // box. Need to work on this.
+  if (os.platform() !== 'win32') {
+    it('should show help when passed an invalid command', function () {
+      const out = cash('banjo kazooie!');
+      out.should.containEql('Cash');
+      out.should.containEql('These shell commands are defined internally');
+    });
+  }
+});
diff --git a/test/kill.js b/test/kill.js
new file mode 100755
index 0000000..f0dcd9b
--- /dev/null
+++ b/test/kill.js
@@ -0,0 +1,78 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+
+describe('kill', function () {
+  it('should exist and be a function', function () {
+    should.exist(cash.kill);
+  });
+
+  it('should show usage when not passed anything', function () {
+    const usage = 'kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]\n';
+    cash.kill().should.equal(usage);
+    cash.kill('').should.equal(usage);
+    cash.kill([]).should.equal(usage);
+  });
+
+  it('should error on an invalid pid', function () {
+    (function () {
+      cash.kill('69696969');
+    }).should.not.throw();
+  });
+
+  it('should error on an invalid process name', function () {
+    // Let's hope Travis doesn't incorporate this game into
+    // every Docker image! It just might happen.
+    (function () {
+      cash.kill('banjokazooie');
+    }).should.not.throw();
+  });
+
+  it('should accept a string of multiple processes', function () {
+    (function () {
+      cash.kill('69696969 banjokazooie');
+    }).should.not.throw();
+  });
+
+  describe('-l', function () {
+    it('should print available signals', function () {
+      cash.kill(undefined, {l: true}).should.equal(` 9) SIGKILL   15) SIGTERM\n`);
+    });
+
+    it('should print the name of a signal number', function () {
+      cash.kill(undefined, {l: 9}).should.equal(`KILL\n`);
+    });
+
+    it('should print the number of a signal name', function () {
+      cash.kill(undefined, {l: 'KILL'}).should.equal(`9\n`);
+    });
+
+    it('should not allow an invalid signal', function () {
+      cash.kill(undefined, {l: 'ALICE-IN-WONDERLAND'}).should
+        .equal(`-cash: kill: ALICE-IN-WONDERLAND: invalid signal specification\n`);
+    });
+  });
+
+  describe('-s', function () {
+    it('should accept SIGKILL', function () {
+      (function () {
+        cash.kill('2342309SDF', {s: 'SIGKILL'});
+      }).should.not.throw();
+    });
+    it('should accept KILL', function () {
+      (function () {
+        cash.kill('2342309SDF', {s: 'KILL'});
+      }).should.not.throw();
+    });
+  });
+
+  describe('-n', function () {
+    it('should accept signal 9', function () {
+      (function () {
+        cash.kill('2342309SDF', {n: 9});
+      }).should.not.throw();
+    });
+  });
+});
diff --git a/test/ls.js b/test/ls.js
new file mode 100755
index 0000000..48f73f6
--- /dev/null
+++ b/test/ls.js
@@ -0,0 +1,171 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const strip = require('../dist/util/stripAnsi.js');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+const util = require('./util/util');
+const os = require('os');
+
+const expected = {
+  rootDirFlat: 'a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g  sub\n',
+  rootDirFlatAll: '.  ..  a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g  .hidden  sub\n',
+  rootDirFlatHidden: 'a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g  .hidden  sub\n',
+  rootDirFlatReversed: 'a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g  sub\n',
+  rootDirFlatClassified: 'a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g  sub/\n',
+  rootDirFlatThinWidth: 'a.txt\nb.tgz\nc.exe\nd.json\ne.gif\nf.jpg\ng\nsub\n',
+  rootDirFlatQuotes: '"a.txt"  "b.tgz"  "c.exe"  "d.json"  "e.gif"  "f.jpg"  "g"  "sub"\n',
+  rootDirFlatByFileSize: 'sub  g  f.jpg  b.tgz  e.gif  d.json  c.exe  a.txt\n',
+  subDirFlat: 'a.txt  b.tgz  c.exe  d.json  e.gif  f.jpg  g\n'
+};
+
+function ls(path, opts) {
+  opts = opts || {};
+  opts.options = opts.options || {};
+  try {
+    const result = cash.ls(path, opts);
+    return result;
+  } catch (e) {
+    console.log(e);
+    throw new Error(e);
+  }
+}
+
+// Appveyor creates some problems
+// that I can't reproduce on any Windows
+// box. Need to work on this.
+if (os.platform() !== 'win32') {
+  describe('ls', function () {
+    before(function (done) {
+      $.mkdir('-p', './atatatest/foo/bar');
+      $.touch('./atatatest/foo/bar/cows.file');
+      util.writeSampleDir(function () {
+        process.chdir('./testing/');
+        done();
+      });
+    });
+
+    after(function () {
+      process.chdir('..');
+      $.rm('-rf', './atatatest');
+      util.deleteSampleDir();
+    });
+
+    describe('directory listings', function () {
+      it('should exist and be a function', function () {
+        should.exist(cash.ls);
+      });
+
+      it('should list current dir as default', function () {
+        const res = ls();
+        strip(res).should.equal(expected.rootDirFlat);
+      });
+
+      it('should list a sub directory', function () {
+        const res = ls('./sub');
+        strip(res).should.equal(expected.subDirFlat);
+      });
+
+      it('should list multiple directories', function () {
+        const res = ls(['.', './sub']);
+        strip(res).should.equal(`.:\n${expected.rootDirFlat}\n./sub:\n${expected.subDirFlat}`);
+      });
+
+      it('should list a parent directory', function () {
+        process.chdir('./sub/');
+        const res = ls('..');
+        strip(res).should.equal(expected.rootDirFlat);
+        process.chdir('..');
+      });
+    });
+
+    describe('sorting', function () {
+      it('should not sort with -U', function () {
+        // This is hard to test as linux sorts
+        // the files by default and windows doesn't
+        const unsorted = ls('.', {U: true});
+        if (os.platform() !== 'win32') {
+          strip(unsorted).should.equal(expected.rootDirFlat);
+        }
+      });
+
+      it('should reverse-sort with -r', function () {
+        const res = ls('.', {r: true});
+        strip(res).should.equal(expected.rootDirFlatReversed);
+      });
+
+      // this is breaking on travis but not in my ubuntu box... weird
+      // have to debug.
+      it.skip('should sort by file size with -S', function () {
+        const res = ls('.', {S: true});
+        strip(res).should.equal(expected.rootDirFlatByFileSize);
+      });
+    });
+
+    describe('file display', function () {
+      it('should list hidden files with --almost-all', function () {
+        const res = ls('.', {almostall: true});
+        strip(res).should.equal(expected.rootDirFlatHidden);
+      });
+
+      it('should list hidden and implied files with --all', function () {
+        const res = ls('.', {all: true});
+        strip(res).should.equal(expected.rootDirFlatAll);
+      });
+
+      it('should list append "/" to folders with --classify', function () {
+        const res = ls('.', {classify: true});
+        strip(res).should.equal(expected.rootDirFlatClassified);
+      });
+
+      it('should add quotes to names with --quote-name', function () {
+        const res = ls('.', {quotename: true});
+        strip(res).should.equal(expected.rootDirFlatQuotes);
+      });
+
+      it('should adjust screen width with --width', function () {
+        const res = ls('.', {width: 5});
+        strip(res).replace(/ /g, '').should.equal(expected.rootDirFlatThinWidth);
+      });
+
+      it('should list entries as flat  -x', function () {
+        const res = ls('.', {x: true});
+        strip(res).should.equal(expected.rootDirFlat);
+      });
+
+      it('should list one file per line with -1', function () {
+        const res = ls('.', {1: true});
+        strip(res).replace(/ /g, '').should.equal(expected.rootDirFlatThinWidth);
+      });
+    });
+
+    describe('long listing', function () {
+      it('should draw long listings with -l', function () {
+        const res = ls('.', {l: true});
+        const out = strip(res);
+        out.should.containEql('total');
+        out.should.containEql('-rw');
+        out.should.containEql(' 1 ');
+        out.should.containEql(' 135 ');
+        out.should.containEql(' e.gif');
+        out.should.containEql(' sub');
+      });
+
+      it('should display human readable numbers of --human-readable', function () {
+        const res = ls('.', {l: true, humanreadable: true});
+        const out = strip(res);
+        out.should.containEql(' 135');
+        out.should.containEql('3.6K');
+      });
+    });
+
+    describe('-r', function () {
+      it('should list recursively with -r', function () {
+        const res = ls('../atatatest', {recursive: true});
+        const out = strip(res);
+        out.should.equal(`../atatatest/foo:\nbar\n\n../atatatest/foo/bar:\ncows.file\n`);
+      });
+    });
+  });
+}
diff --git a/test/mkdir.js b/test/mkdir.js
new file mode 100755
index 0000000..4b33e80
--- /dev/null
+++ b/test/mkdir.js
@@ -0,0 +1,94 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+
+describe('mkdir', function () {
+  before(function () {
+    $.rm('-rf', './testabot*');
+  });
+
+  after(function () {
+    $.rm('-rf', './testabot*');
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.mkdir);
+  });
+
+  it('should show usage when not passed anything', function () {
+    const usage = 'mkdir: missing operand\nTry \'mkdir --help\' for more information.\n';
+    cash.mkdir().should.equal(usage);
+    cash.mkdir('').should.equal(usage);
+    cash.mkdir([]).should.equal(usage);
+  });
+
+  it('should make a dir', function () {
+    $.test('-e', './testabot').should.equal(false);
+    cash.mkdir('testabot');
+    $.test('-e', './testabot').should.equal(true);
+  });
+
+  it('should make multiple dirs', function () {
+    $.test('-e', './testabot-a').should.equal(false);
+    $.test('-e', './testabot-b').should.equal(false);
+    $.test('-e', './testabot-c').should.equal(false);
+    cash.mkdir('testabot-a testabot-b testabot-c');
+    $.test('-e', './testabot-a').should.equal(true);
+    $.test('-e', './testabot-b').should.equal(true);
+    $.test('-e', './testabot-c').should.equal(true);
+    $.rm('-rf', './testabot-a');
+    $.rm('-rf', './testabot-b');
+    $.rm('-rf', './testabot-c');
+  });
+
+  it('accept arrays as an input', function () {
+    $.test('-e', './testabot-a').should.equal(false);
+    $.test('-e', './testabot-b').should.equal(false);
+    $.test('-e', './testabot-c').should.equal(false);
+    cash.mkdir(['testabot-a', 'testabot-b', 'testabot-c']);
+    $.test('-e', './testabot-a').should.equal(true);
+    $.test('-e', './testabot-b').should.equal(true);
+    $.test('-e', './testabot-c').should.equal(true);
+  });
+
+  it('should error on an existing dir', function () {
+    $.test('-e', './testabot').should.equal(true);
+    cash.mkdir('testabot').should.equal('mkdir: cannot create directory testabot: File exists\n');
+  });
+
+  it('should error on a child dir that doesn\'t exist', function () {
+    $.rm('-rf', './testabot');
+    $.test('-e', './testabot').should.equal(false);
+    cash.mkdir('testabot/foo').should
+      .equal('mkdir: cannot create directory testabot/foo: No such file or directory\n');
+  });
+
+  describe('-p', function () {
+    it('should create a child dir that doesn\'t exist', function () {
+      $.rm('-rf', './testabot');
+      $.test('-e', './testabot').should.equal(false);
+      cash.mkdir('testabot/foo', {parents: true});
+      $.test('-e', './testabot/foo').should.equal(true);
+    });
+  });
+
+  describe('-v', function () {
+    it('should print a message on a single directory created', function () {
+      $.rm('-rf', './testabot');
+      $.test('-e', './testabot').should.equal(false);
+      cash.mkdir('testabot', {verbose: true}).should.equal('mkdir: created directory testabot\n');
+      $.test('-e', './testabot').should.equal(true);
+    });
+
+    it('should print a message on a -p directory created', function () {
+      $.rm('-rf', './testabot');
+      $.test('-e', './testabot').should.equal(false);
+      cash.mkdir('testabot/foo', {parents: true, verbose: true}).should
+        .equal('mkdir: created directory testabot\nmkdir: created directory testabot/foo\n');
+      $.test('-e', './testabot/foo').should.equal(true);
+    });
+  });
+});
diff --git a/test/mv.js b/test/mv.js
new file mode 100755
index 0000000..b24a7c2
--- /dev/null
+++ b/test/mv.js
@@ -0,0 +1,125 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+
+function burninate() {
+  $.rm('-rf', './mvtemp');
+  $.rm('-rf', 'mv-a');
+  $.rm('-rf', 'mv-b');
+  $.rm('-rf', 'mv-c');
+  $.rm('-rf', 'mv-d');
+  $.rm('-rf', 'mv-e');
+}
+
+function reset() {
+  burninate();
+  $.mkdir('mvtemp');
+  $.touch('mv-a');
+  $.touch('mv-b');
+  $.touch('mv-c');
+}
+
+describe('mv', function () {
+  before(function () {
+    burninate();
+  });
+
+  after(function () {
+    burninate();
+  });
+
+  beforeEach(function () {
+    reset();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.mv);
+  });
+
+  it('should show usage when not passed anything', function () {
+    const usage = 'mv: missing file operand\nTry \'mv --help\' for more information.\n';
+    cash.mv().should.equal(usage);
+    cash.mv('').should.equal(usage);
+    cash.mv([]).should.equal(usage);
+  });
+
+  it('should show usage when passed only one param', function () {
+    const usage = 'mv: missing destination file operand after foo\nTry \'mv --help\' for more information.\n';
+    cash.mv('foo').should.equal(usage);
+    cash.mv(['foo']).should.equal(usage);
+  });
+
+  it('should move a file', function () {
+    cash.mv('mv-a mvtemp/mv-a');
+    $.test('-e', './mvtemp/mv-a').should.equal(true);
+  });
+
+  it('should move multiple files', function () {
+    cash.mv('mv-a mv-b mvtemp');
+    $.test('-e', './mvtemp/mv-a').should.equal(true);
+    $.test('-e', './mvtemp/mv-b').should.equal(true);
+  });
+
+  it('should only accept directories on multiple files', function () {
+    cash.mv('mv-a mv-b mvtemp/mv-cows').should
+      .equal('mv: target mvtemp/mv-cows is not a directory\n');
+  });
+
+  it('should skip and give message on non-existing src files', function () {
+    const msg =
+      'mv: cannot stat mv-vorpal: No such file or directory\n' +
+      'mv: cannot stat mv-howdy: No such file or directory\n';
+    cash.mv('mv-a mv-b mv-vorpal mv-c mv-howdy mvtemp').should
+      .equal(msg);
+    $.test('-e', './mvtemp/mv-a').should.equal(true);
+    $.test('-e', './mvtemp/mv-b').should.equal(true);
+    $.test('-e', './mvtemp/mv-c').should.equal(true);
+  });
+
+  it('should rename a file', function () {
+    cash.mv('mv-a mv-d');
+    $.test('-e', 'mv-d').should.equal(true);
+    $.test('-e', 'mv-a').should.equal(false);
+  });
+
+  it('should clobber existing files', function () {
+    'foxes'.to('mv-d');
+    'elephants'.to('mv-e');
+    cash.mv('mv-d mv-e');
+    $.test('-e', 'mv-d').should.equal(false);
+    $.cat('mv-e').should.equal('foxes');
+  });
+
+  describe('-n', function () {
+    it('should not clobber existing files', function () {
+      'foxes'.to('mv-d');
+      'elephants'.to('mv-e');
+      cash.mv('mv-d mv-e', {noclobber: true}).should.equal('');
+      $.test('-e', 'mv-d').should.equal(true);
+      $.cat('mv-d').should.equal('foxes');
+      $.cat('mv-e').should.equal('elephants');
+    });
+  });
+
+  describe('-f', function () {
+    it('should overwrite -n', function () {
+      'foxes'.to('mv-d');
+      'elephants'.to('mv-e');
+      cash.mv('mv-d mv-e', {noclobber: true, force: true});
+      $.test('-e', 'mv-d').should.equal(false);
+      $.cat('mv-e').should.equal('foxes');
+    });
+  });
+
+  describe('-v', function () {
+    it('should print verbose messages', function () {
+      cash.mv('mv-a mv-b mvtemp', {verbose: true}).should
+        .equal('mv-a -> mvtemp/mv-a\nmv-b -> mvtemp/mv-b\n');
+      $.test('-e', './mvtemp/mv-a').should.equal(true);
+      $.test('-e', './mvtemp/mv-b').should.equal(true);
+    });
+  });
+});
diff --git a/test/pwd.js b/test/pwd.js
new file mode 100755
index 0000000..b7873a4
--- /dev/null
+++ b/test/pwd.js
@@ -0,0 +1,23 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+
+describe('pwd', function () {
+  it('should exist and be a function', function () {
+    should.exist(cash.pwd);
+  });
+
+  it('should print the current working directory', function () {
+    cash.pwd().should.containEql('cash');
+  });
+
+  it('should change on directory change', function () {
+    String(cash.pwd()).should.not.containEql('node_modules');
+    $.cd('./node_modules');
+    String(cash.pwd()).should.containEql('node_modules');
+    $.cd('..');
+  });
+});
diff --git a/test/rm.js b/test/rm.js
new file mode 100755
index 0000000..5083857
--- /dev/null
+++ b/test/rm.js
@@ -0,0 +1,89 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const fs = require('fs');
+const $ = require('shelljs');
+require('shelljs/global');
+
+describe('rm', function () {
+  before(function () {
+    $.mkdir('rm-test');
+    $.mkdir('./rm-test/sub');
+    '1'.to('1.rm');
+    'a'.to('./rm-test/a.txt');
+    'b'.to('./rm-test/b.txt');
+    'c'.to('./rm-test/c.txt');
+    'd'.to('./rm-test/sub/d.txt');
+    'cow'.to('./rm-test/a.cows');
+    'cow'.to('./rm-test/b.cows');
+    'cow'.to('./rm-test/c.cows');
+    'goose'.to('./rm-test/a.goose');
+    'goose'.to('./rm-test/b.goose');
+  });
+
+  after(function () {
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.rm);
+  });
+
+  it('should remove a file', function () {
+    ($.ls('.').indexOf('1.rm')).should.be.above(-1);
+    cash.rm('1.rm');
+    ($.ls('.').indexOf('1.rm')).should.equal(-1);
+  });
+
+  it('should remove from a subdirectory', function () {
+    ($.ls('./rm-test').indexOf('a.txt')).should.be.above(-1);
+    cash.rm('./rm-test/a.txt');
+    ($.ls('./rm-test').indexOf('a.txt')).should.equal(-1);
+  });
+
+  it('should remove mutiple files at once', function () {
+    cash.rm('./rm-test/a.goose');
+    cash.rm('./rm-test/b.goose');
+    ($.ls('./rm-test').indexOf('a.goose')).should.equal(-1);
+    ($.ls('./rm-test').indexOf('b.goose')).should.equal(-1);
+  });
+
+  it('should remove based on wildcards / regex', function () {
+    cash.rm('./rm-test/*.cows');
+    ($.ls('./rm-test').indexOf('a.cows')).should.equal(-1);
+    ($.ls('./rm-test').indexOf('b.cows')).should.equal(-1);
+    ($.ls('./rm-test').indexOf('c.cows')).should.equal(-1);
+  });
+
+  it('should not remove a dir that doesn\'t exist', function () {
+    cash.rm('./bllasdlfjsd')
+      .should.equal(`rm: cannot remove ./bllasdlfjsd: No such file or directory\n`);
+    ($.ls('./rm-test').indexOf('a.txt')).should.equal(-1);
+  });
+
+  it('should not remove a directory without -r', function () {
+    const out = cash.rm('rm-test');
+    out.should.equal('rm: cannot remove: path is a directory\n');
+  });
+
+  describe('rm -r', function () {
+    it('should recursively remove directories and files', function () {
+      ($.ls('.').indexOf('rm-test')).should.not.equal(-1);
+      cash.rm('./rm-test', {recursive: true});
+      ($.ls('.').indexOf('rm-test')).should.equal(-1);
+    });
+  });
+
+  describe('rm -f', function () {
+    it('should remove a read only file with', function () {
+      $.mkdir('-p', './rm-temp/readonly');
+      'asdf'.to('./rm-temp/readonly/file2');
+      fs.chmodSync('./rm-temp/readonly/file2', '0444'); // -r--r--r--
+      cash.rm('./rm-temp/readonly/file2', {force: true});
+      ($.ls('.').indexOf('./rm-temp/readonly/file2')).should.equal(-1);
+      cash.rm('./rm-temp', {recursive: true});
+      ($.ls('.').indexOf('./rm-temp')).should.equal(-1);
+    });
+  });
+});
diff --git a/test/sort.js b/test/sort.js
new file mode 100755
index 0000000..84b1ffa
--- /dev/null
+++ b/test/sort.js
@@ -0,0 +1,139 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+require('shelljs/global');
+
+function sort(dir, opts) {
+  opts = opts || {};
+  opts.options = opts.options || {};
+  try {
+    return cash.sort(dir, opts);
+  } catch (e) {
+    console.log(e);
+    throw new Error(e);
+  }
+}
+
+describe('sort', function () {
+  before(function (done) {
+    setTimeout(function () {
+      'zaz\nsss\nqqq\n-zbz\nBBB\nddd\nCCC\n2bbb\nccc\n'.to('./default.sort');
+      '22 zaz\n33 sss\n11 qqq\n77 ccc\n55 BBB\nddd\nCCC\n2bbb\n-zbz\n'.to('./numeric.sort');
+      '1k\na 2G\n8k\n1M\n.8K\nddd\nCCC\n7bbb\n1bbb\n5M\n4G\n3T\n2.5P\n2E\n1Z\n6bbb\n5bbb\n-zbz\n'.to('./human.sort');
+      '4mar\nMarch\nMarc\napr\nAPR\ngoats\n56sevenjan\njan345kds\ndec\ndecem\nau\nAuGuSt\nAuGurt\naug\naugust\n'.to('./month.sort');
+      '1\n2\n3\n4\n5\n26\n7\n8\n9\n10\n11\n'.to('./disorder-numeric.sort');
+      'a\nb\nc\nd\nf\ne\ng\n'.to('./disorder.sort');
+      '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n'.to('./numbers.sort');
+      done();
+    }, 100);
+  });
+
+  after(function () {
+    $.rm('*.sort');
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.sort);
+  });
+
+  it('should do nothing when called by itself', function () {
+    const results = sort();
+    results.should.equal('');
+  });
+
+  it('should properly sort a single file', function () {
+    const results = sort('default.sort');
+    results.should.equal('2bbb\nBBB\nccc\nCCC\nddd\nqqq\nsss\nzaz\n-zbz\n');
+  });
+
+  it('should sort multiple files in a combined fashion', function () {
+    const results = sort(['default.sort', 'default.sort']);
+    results.should.equal('2bbb\n2bbb\nBBB\nBBB\nccc\nccc\nCCC\nCCC\nddd\nddd\nqqq\nqqq\nsss\nsss\nzaz\nzaz\n-zbz\n-zbz\n');
+  });
+
+  describe('sort -n', function () {
+    it('should compare according to string numerical value', function () {
+      const results = sort('numeric.sort', {numericsort: true});
+      results.should.equal('CCC\nddd\n-zbz\n2bbb\n11 qqq\n22 zaz\n33 sss\n55 BBB\n77 ccc\n');
+    });
+  });
+
+  describe('sort -h', function () {
+    it('should compare human readable numbers (e.g., 2K 1G)', function () {
+      const results = sort('human.sort', {humannumericsort: true});
+      results.should.equal('a 2G\nCCC\nddd\n-zbz\n1bbb\n5bbb\n6bbb\n7bbb\n.8K\n1k\n8k\n1M\n5M\n4G\n3T\n2.5P\n2E\n1Z\n');
+    });
+  });
+
+  describe('sort -m', function () {
+    it('should compare (unknown) < \'JAN\' < ... < \'DEC\'', function () {
+      const results = sort('month.sort', {monthsort: true});
+      results.should.equal('4mar\n56sevenjan\nau\ngoats\njan345kds\nMarc\nMarch\napr\nAPR\naug\nAuGurt\naugust\nAuGuSt\ndec\ndecem\n');
+    });
+  });
+
+  describe('sort -c', function () {
+    it('should check for sorted input', function () {
+      const results = sort('disorder.sort', {check: true});
+      results.should.equal('sort: -:6: disorder: e\n');
+    });
+
+    it('should check for sorted numeric input', function () {
+      const results = sort('disorder-numeric.sort', {check: true});
+      results.should.equal('sort: -:6: disorder: 26\n');
+    });
+  });
+
+  describe('sort -r', function () {
+    it('should reverse the result of comparisons', function () {
+      sort('default.sort', {reverse: true})
+        .should.equal('-zbz\nzaz\nsss\nqqq\nddd\nCCC\nccc\nBBB\n2bbb\n');
+    });
+
+    it('should reverse multiple-file comparisons', function () {
+      sort(['default.sort', 'default.sort'], {reverse: true})
+        .should.equal('-zbz\n-zbz\nzaz\nzaz\nsss\nsss\nqqq\nqqq\nddd\nddd\nCCC\nCCC\nccc\nccc\nBBB\nBBB\n2bbb\n2bbb\n');
+    });
+
+    it('should reverse operations using other options', function () {
+      sort('human.sort', {humannumericsort: true, reverse: true})
+        .should.equal('1Z\n2E\n2.5P\n3T\n4G\n5M\n1M\n8k\n1k\n.8K\n7bbb\n6bbb\n5bbb\n1bbb\n-zbz\nddd\nCCC\na 2G\n');
+    });
+  });
+
+  describe('sort -o', function () {
+    it('should write result to file instead of standard output', function () {
+      sort('default.sort', {output: 'default-out.sort'}).should.equal('');
+      cash.cat('default-out.sort').should.equal('2bbb\nBBB\nccc\nCCC\nddd\nqqq\nsss\nzaz\n-zbz\n');
+    });
+
+    it('should shit on you for passing no argument to "--output', function () {
+      sort('default.sort', {output: true})
+        .should.equal('sort: option \'--output\' requires an argument\nTry \'sort --help\' for more information.\n');
+    });
+
+    it('should shit on you for passing an invalid file', function () {
+      // Yeah, I'm a muggle.
+      sort('default.sort', {output: './platform/nine/and/three/quarters.sort'})
+        .should.equal('sort: open failed: ./platform/nine/and/three/quarters.sort: No such file or directory\n');
+    });
+  });
+
+  describe('sort -R', function () {
+    // I use currently use the Fisher Yates shuffle,
+    // Bostock style. Yes, I know, sorting arrays has woes.
+    it('should sort by a random hash of keys', function () {
+      let last = '';
+      // Is 20 factorial sufficient entropy? What are the
+      // odds of my test failing? :)
+      for (let i = 0; i < 100; ++i) {
+        const results = sort('numbers.sort', {randomsort: true});
+        results.should.not.equal(last);
+        last = results;
+      }
+    });
+  });
+});
diff --git a/test/touch.js b/test/touch.js
new file mode 100755
index 0000000..b2abd27
--- /dev/null
+++ b/test/touch.js
@@ -0,0 +1,125 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const util = require('./util/util');
+const fs = require('fs-extra');
+
+describe('touch', function () {
+  before(function (done) {
+    util.writeSampleDir(function () {
+      process.chdir('./testing/');
+      done();
+    });
+  });
+
+  after(function () {
+    process.chdir('..');
+    util.deleteSampleDir();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.touch);
+  });
+
+  it('should create a file where none exists', function () {
+    cash.touch('fizzle');
+    const stat = fs.statSync('fizzle');
+    stat.should.exist;
+  });
+
+  it('should update the atime and mtime of a file that does exist', function () {
+    cash.touch('fizzle', {
+      date: '1 January 1980'
+    });
+    const stat = fs.statSync('fizzle');
+    const atime = new Date(stat.atime);
+    const mtime = new Date(stat.mtime);
+    cash.touch('fizzle');
+    const stat2 = fs.statSync('fizzle');
+    const atime2 = new Date(stat2.atime);
+    const mtime2 = new Date(stat2.mtime);
+    ((atime2 - atime) > 0).should.equal(true);
+    ((mtime2 - mtime) > 0).should.equal(true);
+  });
+
+  it('should handle multiple files gracefully', function () {
+    cash.touch(['wizzle', 'fizzle']);
+    (function () {
+      fs.statSync('fizzle');
+      fs.statSync('wizzle');
+    }).should.not.throw();
+  });
+
+  it('should set custom times with --date', function () {
+    cash.touch('fizzle', {
+      date: '1 January 1980'
+    });
+    let stat;
+    (function () {
+      stat = fs.statSync('fizzle');
+    }).should.not.throw();
+    stat.atime.getFullYear().should.equal(1980);
+    stat.mtime.getFullYear().should.equal(1980);
+  });
+
+  it('should only change the access time with -a', function () {
+    cash.touch('fizzle', {
+      a: true,
+      date: '1 January 1976'
+    });
+    let stat;
+    (function () {
+      stat = fs.statSync('fizzle');
+    }).should.not.throw();
+    stat.atime.getFullYear().should.equal(1976);
+    stat.mtime.getFullYear().should.equal(1980);
+  });
+
+  it('should use another file\'s times with --reference', function () {
+    cash.touch('wizzle', {
+      reference: 'fizzle'
+    });
+    let stat;
+    (function () {
+      stat = fs.statSync('wizzle');
+    }).should.not.throw();
+    stat.atime.getFullYear().should.equal(1976);
+    stat.mtime.getFullYear().should.equal(1980);
+  });
+
+  it('should use --time as an alias for -a or -m', function () {
+    cash.touch('fizzle', {
+      time: 'access',
+      date: '1 January 1972'
+    });
+    let stat;
+    (function () {
+      stat = fs.statSync('fizzle');
+    }).should.not.throw();
+    stat.atime.getFullYear().should.equal(1972);
+    stat.mtime.getFullYear().should.equal(1980);
+  });
+
+  it('should throw on invalid --time parameter', function () {
+    const results = cash.touch('fizzle', {
+      time: 'notime!'
+    });
+    results.should.containEql('touch: invalid argument "notime!"');
+  });
+
+  it('should throw on invalid --date parameter', function () {
+    const results = cash.touch('fizzle', {
+      date: 'at the prom?'
+    });
+    results.should.containEql('touch: invalid date format');
+  });
+
+  it('should throw on invalid --reference parameter', function () {
+    const results = cash.touch('fizzle', {
+      reference: 'themissingfile'
+    });
+    results.should.containEql('touch: failed to get attributes');
+  });
+});
diff --git a/test/unalias.js b/test/unalias.js
new file mode 100755
index 0000000..3f5c2c8
--- /dev/null
+++ b/test/unalias.js
@@ -0,0 +1,71 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+
+// Cleans all alias junk out of
+// localStorage.
+function clear() {
+  cash._aliases = {};
+  const ls = cash.vorpal.localStorage._localStorage;
+  cash.vorpal.localStorage.removeItem('aliases');
+  ls.keys = ls.keys.filter(function (key) {
+    if (String(key).indexOf('alias|') > -1) {
+      delete ls.metaKeyMap[key];
+      return false;
+    }
+  });
+}
+
+describe('alias', function () {
+  before(function () {
+    clear();
+  });
+
+  after(function () {
+    clear();
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.unalias);
+  });
+
+  it('should show usage when not passed anything', function () {
+    cash.unalias().should.equal('unalias: usage: unalias [-a] name [name ...]\n');
+    cash.unalias('').should.equal('unalias: usage: unalias [-a] name [name ...]\n');
+    cash.unalias([]).should.equal('unalias: usage: unalias [-a] name [name ...]\n');
+  });
+
+  it('should remove an alias', function () {
+    cash.alias('foo=bar');
+    cash.alias('foo').should.equal('alias foo=\'bar\'\n');
+    cash.unalias('foo');
+    cash.alias('foo').should.equal('-cash: alias: foo: not found\n');
+  });
+
+  it('should remove multiple aliases', function () {
+    cash.alias('foo=bar');
+    cash.alias('fizz buzz');
+    cash.alias('foo').should.equal('alias foo=\'bar\'\n');
+    cash.alias('fizz').should.equal('alias fizz=\'buzz\'\n');
+    cash.unalias('foo fizz');
+    cash.alias('foo').should.equal('-cash: alias: foo: not found\n');
+    cash.alias('fizz').should.equal('-cash: alias: fizz: not found\n');
+  });
+
+  it('should chuck norris roundhouse kick you on an invalid alias', function () {
+    cash.unalias('foo');
+    cash.unalias('chucknorrisweakspot').should.equal('-cash: unalias: chucknorrisweakspot: not found\n');
+  });
+
+  describe('-a', function () {
+    it('should remove all registered aliases', function () {
+      cash.alias('foo=bar');
+      cash.alias('fizz buzz');
+      cash.unalias(undefined, {a: true});
+      cash.alias('foo').should.equal('-cash: alias: foo: not found\n');
+      cash.alias('fizz').should.equal('-cash: alias: fizz: not found\n');
+    });
+  });
+});
diff --git a/test/util/playground.js b/test/util/playground.js
new file mode 100755
index 0000000..ea13022
--- /dev/null
+++ b/test/util/playground.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const cash = require('../../dist/index.js');
+
+
+let result = cash('fooo!!!!!');
+
+console.log('!!!!!!!!!' + result);
+console.log('----------------');
\ No newline at end of file
diff --git a/test/util/util.js b/test/util/util.js
new file mode 100755
index 0000000..049fa65
--- /dev/null
+++ b/test/util/util.js
@@ -0,0 +1,54 @@
+'use strict';
+
+const $ = require('shelljs');
+const fs = require('fs-extra');
+
+module.exports = {
+
+  writeSampleDir(cb) {
+    // If tests fail mid, script cleanup doesn't happen.
+    // This makes sure we are in the right dir before
+    // trying to write.
+    if (String(process.cwd()).indexOf('/cash') === -1) {
+      process.chdir(`${__dirname}/../..`);
+    }
+
+    fs.removeSync('./testing');
+
+    $.mkdir('-p', './testing/');
+    $.mkdir('-p', './testing/sub/');
+
+    let filler = 'fill|';
+
+    function writeDir(dir, cbk) {
+      const files = ['a.txt', 'c.exe', 'd.json', 'e.gif', 'b.tgz', 'f.jpg', 'g', '.hidden'];
+      function write() {
+        const next = files.shift();
+        if (next) {
+          filler = double(filler);
+          filler.to(dir + next);
+          setTimeout(function () {
+            write();
+          }, 10);
+        } else {
+          cbk();
+        }
+      }
+      write();
+    }
+
+    writeDir('./testing/', function () {
+      writeDir('./testing/sub/', function () {
+        cb();
+      });
+    });
+  },
+
+  deleteSampleDir() {
+    fs.removeSync('./testing');
+  }
+};
+
+function double(str) {
+  return str + str + str.slice(0, 100);
+}
diff --git a/test/vorpal.js b/test/vorpal.js
new file mode 100755
index 0000000..5b21494
--- /dev/null
+++ b/test/vorpal.js
@@ -0,0 +1,30 @@
+'use strict';
+
+require('assert');
+const should = require('should');
+const cash = require('../dist/index.js');
+const commands = require('../commands.json');
+
+describe('vorpal', function () {
+  it('should exist', function () {
+    should.exist(cash);
+  });
+
+  it('should execute all commands without erroring', function () {
+    (function () {
+      const cmds = commands.commands;
+      for (let i = 0; i < cmds.length; ++i) {
+        cash(`${cmds[i]}`);
+      }
+    }).should.not.throw();
+  });
+
+  it('should require commands without vorpal', function () {
+    (function () {
+      const cmds = commands.commands;
+      for (let i = 0; i < cmds.length; ++i) {
+        require(`../dist/commands/${cmds[i]}.js`)();
+      }
+    }).should.not.throw();
+  });
+});
diff --git a/test/windows.js b/test/windows.js
new file mode 100755
index 0000000..2887d5a
--- /dev/null
+++ b/test/windows.js
@@ -0,0 +1,11 @@
+'use strict';
+
+require('assert');
+require('should');
+const cash = require('../dist/index.js');
+
+describe('windows', function () {
+  it('execute a catch command', function () {
+    cash('cash-test');
+  });
+});
