diff --git a/bin/head.js b/bin/head.js
new file mode 100644
index 0000000..ceff3d9
--- /dev/null
+++ b/bin/head.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'head');
diff --git a/commands.json b/commands.json
index 712b5f3..74ac032 100755
--- a/commands.json
+++ b/commands.json
@@ -1,10 +1,12 @@
 {
   "commands": [
     "alias",
+    "cat",
     "cd",
     "clear",
     "cp",
     "echo",
+    "head",
     "export",
     "false",
     "kill",
@@ -17,7 +19,6 @@
     "tail",
     "touch",
     "true",
-    "cat",
     "less",
     "grep",
     "rm",
diff --git a/dist/commands/cat.js b/dist/commands/cat.js
index e1f0abb..d219e51 100755
--- a/dist/commands/cat.js
+++ b/dist/commands/cat.js
@@ -84,10 +84,14 @@ var cat = {
           // If -E, append a $ to each line end.
           var dollarStr = options.showends ? '$' : '';
           var line = numStr + parts[j] + dollarStr;
-          self.log(line);
           stdout += line + '\n';
         }
       }
+
+      if (stdout.length > 0) {
+        self.log(stdout.slice(0, stdout.length - 1));
+      }
+
       return 0;
     } catch (e) {
       /* istanbul ignore next */
diff --git a/dist/commands/head.js b/dist/commands/head.js
new file mode 100644
index 0000000..54fe002
--- /dev/null
+++ b/dist/commands/head.js
@@ -0,0 +1,90 @@
+'use strict';
+
+var interfacer = require('./../util/interfacer');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var head = {
+  exec: function exec(args, options) {
+    var self = this;
+    options = options || {};
+
+    options.argsType = args.stdin === undefined ? 'files' : 'stdin';
+    options.n = options.n === undefined ? 10 : options.n;
+
+    if (options.n < 1) {
+      self.log('Option n must be a positive integer.');
+      return 1;
+    }
+
+    if (options.argsType === 'stdin') {
+      self.log(head.readLines(args.stdin[0], options.n));
+      return 0;
+    }
+
+    var files = args.files || args;
+    files = files === undefined ? [] : files;
+    files = typeof files === 'string' ? String(files).split(' ') : files;
+    files = files.filter(function (arg) {
+      return String(arg).trim() !== '';
+    });
+
+    var stdout = '';
+    var writeHeaders = false;
+    if (files.length > 1) {
+      writeHeaders = true;
+    }
+
+    var content = [];
+    for (var i = 0; i < files.length; i++) {
+      try {
+        content[i] = fs.readFileSync(files[i]).toString();
+      } catch (e) {
+        self.log('head: ' + files[i] + ': No such file or directory');
+        return 1;
+      }
+    }
+
+    for (var i = 0; i < files.length; i++) {
+      if (writeHeaders) {
+        stdout += (i > 0 ? '\n\n' : '') + '==> ' + files[i] + ' <==\n';
+      }
+
+      stdout += head.readLines(content[i], options.n);
+    }
+
+    self.log(stdout);
+    return 0;
+  },
+  readLines: function readLines(content, numberOfLines) {
+    var stdout = '';
+    var contentArray = content.split('\n');
+    var linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines;
+    for (var i = 0; i < linesToRead; i++) {
+      if (stdout === '') {
+        stdout = contentArray[i];
+        continue;
+      }
+
+      stdout += '\n' + contentArray[i];
+    }
+
+    return stdout;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return head;
+  }
+  vorpal.api.head = head;
+  vorpal.command('head [files...]').option('-n [number]', 'The first number of lines will be copied to stdout.').autocomplete(fsAutocomplete()).action(function (args, callback) {
+    args.options = args.options || {};
+    return interfacer.call(this, {
+      command: head,
+      args: args,
+      options: args.options,
+      callback: callback
+    });
+  });
+};
\ No newline at end of file
diff --git a/dist/help/head.js b/dist/help/head.js
new file mode 100644
index 0000000..b825824
--- /dev/null
+++ b/dist/help/head.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: head [OPTION] [files ...]\nShow first lines of file(s).\n\nReport head 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/commands/cat.js b/packages/cat/dist/commands/cat.js
index e1f0abb..f2b1b7b 100755
--- a/packages/cat/dist/commands/cat.js
+++ b/packages/cat/dist/commands/cat.js
@@ -84,10 +84,13 @@ var cat = {
           // If -E, append a $ to each line end.
           var dollarStr = options.showends ? '$' : '';
           var line = numStr + parts[j] + dollarStr;
-          self.log(line);
           stdout += line + '\n';
         }
       }
+
+      if (stdout.length > 0) {
+        self.log(stdout.slice(0, stdout.length - 1));
+      }
       return 0;
     } catch (e) {
       /* istanbul ignore next */
diff --git a/packages/head/README.md/template.README.md b/packages/head/README.md/template.README.md
new file mode 100755
index 0000000..1a8a2a6
--- /dev/null
+++ b/packages/head/README.md/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/head/bin/head.js b/packages/head/bin/head.js
new file mode 100644
index 0000000..ceff3d9
--- /dev/null
+++ b/packages/head/bin/head.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'head');
diff --git a/packages/head/bin/parser.js b/packages/head/bin/parser.js
new file mode 100755
index 0000000..df2a466
--- /dev/null
+++ b/packages/head/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/head/package.json b/packages/head/package.json
new file mode 100755
index 0000000..4778efe
--- /dev/null
+++ b/packages/head/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/src/commands/cat.js b/src/commands/cat.js
index 9c514eb..7616b93 100755
--- a/src/commands/cat.js
+++ b/src/commands/cat.js
@@ -82,18 +82,22 @@ const cat = {
             ctr++;
           }
           const numStr = (numbered) ?
-            `${lpad(String(ctr), 6, ' ')}  ` :
-            '';
+              `${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);
+              numStr +
+              parts[j] +
+              dollarStr;
           stdout += `${line}\n`;
         }
       }
+
+      if (stdout.length > 0) {
+        self.log(stdout.slice(0, stdout.length - 1));
+      }
+
       return 0;
     } catch (e) {
       /* istanbul ignore next */
@@ -110,25 +114,25 @@ module.exports = function (vorpal) {
   }
   vorpal.api.cat = cat;
   vorpal
-    .command('cat [files...]')
-    .parse(preparser)
-    .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
+      .command('cat [files...]')
+      .parse(preparser)
+      .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/head.js b/src/commands/head.js
new file mode 100644
index 0000000..ac97fc2
--- /dev/null
+++ b/src/commands/head.js
@@ -0,0 +1,94 @@
+'use strict';
+
+const interfacer = require('./../util/interfacer');
+const fs = require('fs');
+const fsAutocomplete = require('vorpal-autocomplete-fs');
+
+const head = {
+
+  exec(args, options) {
+    const self = this;
+    options = options || {};
+
+    options.argsType = args.stdin === undefined ? 'files' : 'stdin';
+    options.n = options.n === undefined ? 10 : options.n;
+
+    if (options.n < 1) {
+      self.log('Option n must be a positive integer.');
+      return 1;
+    }
+
+    if (options.argsType === 'stdin') {
+      self.log(head.readLines(args.stdin[0], options.n));
+      return 0;
+    }
+
+    let files = args.files || args;
+    files = (files === undefined) ? [] : files;
+    files = (typeof files === 'string') ? String(files).split(' ') : files;
+    files = files.filter(arg => String(arg).trim() !== '');
+
+    let stdout = '';
+    let writeHeaders = false;
+    if (files.length > 1) {
+      writeHeaders = true;
+    }
+
+    const content = [];
+    for (let i = 0; i < files.length; i++) {
+      try {
+        content[i] = fs.readFileSync(files[i]).toString();
+      } catch (e) {
+        self.log(`head: ${files[i]}: No such file or directory`);
+        return 1;
+      }
+    }
+
+    for (let i = 0; i < files.length; i++) {
+      if (writeHeaders) {
+        stdout += `${i > 0 ? '\n\n' : ''}==> ${files[i]} <==\n`;
+      }
+
+      stdout += head.readLines(content[i], options.n);
+    }
+
+    self.log(stdout);
+    return 0;
+  },
+
+  readLines(content, numberOfLines) {
+    let stdout = '';
+    const contentArray = content.split('\n');
+    const linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines;
+    for (let i = 0; i < linesToRead; i++) {
+      if (stdout === '') {
+        stdout = contentArray[i];
+        continue;
+      }
+
+      stdout += `\n${contentArray[i]}`;
+    }
+
+    return stdout;
+  }
+};
+
+module.exports = function (vorpal) {
+  if (vorpal === undefined) {
+    return head;
+  }
+  vorpal.api.head = head;
+  vorpal
+      .command('head [files...]')
+      .option('-n [number]', 'The first number of lines will be copied to stdout.')
+      .autocomplete(fsAutocomplete())
+      .action(function (args, callback) {
+        args.options = args.options || {};
+        return interfacer.call(this, {
+          command: head,
+          args,
+          options: args.options,
+          callback
+        });
+      });
+};
diff --git a/src/help.js b/src/help.js
index c79e626..bad7978 100755
--- a/src/help.js
+++ b/src/help.js
@@ -12,6 +12,7 @@ const commands = [
   'export [-p][id=[value]]',
   'false',
   'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]',
+  'head [-n number] [files...]',
   'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l',
   'less [files ...]',
   'ls [-aAdFhilQrRStUwx1] [paths ...]',
diff --git a/src/help/head.js b/src/help/head.js
new file mode 100644
index 0000000..478ff3d
--- /dev/null
+++ b/src/help/head.js
@@ -0,0 +1,7 @@
+module.exports = `
+Usage: head [OPTION] [files ...]
+Show first lines of file(s).
+
+Report head bugs to <https://github.com/dthree/cash>
+Cash home page: <http://cash.js.org/>
+`;
diff --git a/test/head.js b/test/head.js
new file mode 100644
index 0000000..724191f
--- /dev/null
+++ b/test/head.js
@@ -0,0 +1,38 @@
+'use strict';
+
+require('assert');
+require('mocha');
+const should = require('should');
+const cash = require('../dist/index.js');
+const $ = require('shelljs');
+require('shelljs/global');
+
+describe('head', function () {
+  before(function () {
+    'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\nline11'.to('eleven.test');
+    'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10'.to('ten.test');
+  });
+
+  after(function () {
+    $.rm(['eleven.test', 'ten.test']);
+  });
+
+  it('should exist and be a function', function () {
+    should.exist(cash.head);
+  });
+
+  it('should give back ten lines when called without options', function () {
+    const result = cash.head('eleven.test');
+    result.should.be.equal('line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\n');
+  });
+
+  it('should give back five lines when called with option n set to 5', function () {
+    const result = cash.head('eleven.test', {n: 5});
+    result.should.be.equal('line1\nline2\nline3\nline4\nline5\n');
+  });
+
+  it('should write header when used with more than one file', function () {
+    const result = cash.head(['eleven.test', 'ten.test'], {n: 2});
+    result.should.be.equal('==> eleven.test <==\nline1\nline2\n\n==> ten.test <==\nline1\nline2\n');
+  });
+});
