diff --git a/src/node/bin/README.md b/src/node/bin/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2f856e428ef7b8ad9723e503f09685a8a4ec77e8
--- /dev/null
+++ b/src/node/bin/README.md
@@ -0,0 +1,16 @@
+# Command Line Tools
+
+# Service Packager
+
+The command line tool `bin/service_packager`, when called with the following command line:
+
+```bash
+service_packager proto_file -o output_path -n name -v version [-i input_path...]
+```
+
+Populates `output_path` with a node package consisting of a `package.json` populated with `name` and `version`, an `index.js`, a `LICENSE` file copied from gRPC, and a `service.json`, which is compiled from `proto_file` and the given `input_path`s. `require('output_path')` returns an object that is equivalent to
+
+```js
+{ client: require('grpc').load('service.json'),
+  auth: require('google-auth-library') }
+```
diff --git a/src/node/bin/service_packager b/src/node/bin/service_packager
new file mode 100755
index 0000000000000000000000000000000000000000..c7f24609977eee53c6ccda137b057ddb1aadbc60
--- /dev/null
+++ b/src/node/bin/service_packager
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require(__dirname+'/../cli/service_packager.js').main(process.argv.slice(2));
\ No newline at end of file
diff --git a/src/node/cli/service_packager.js b/src/node/cli/service_packager.js
new file mode 100644
index 0000000000000000000000000000000000000000..f29180b2526830fad809438fed63f4f837aee747
--- /dev/null
+++ b/src/node/cli/service_packager.js
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var _ = require('underscore');
+var async = require('async');
+var pbjs = require('protobufjs/cli/pbjs');
+var parseArgs = require('minimist');
+var Mustache = require('mustache');
+
+var package_json = require('../package.json');
+
+var template_path = path.resolve(__dirname, 'service_packager');
+
+var package_tpl_path = path.join(template_path, 'package.json.template');
+
+var arg_format = {
+  string: ['include', 'out', 'name', 'version'],
+  alias: {
+    include: 'i',
+    out: 'o',
+    name: 'n',
+    version: 'v'
+  }
+};
+
+// TODO(mlumish): autogenerate README.md from proto file
+
+/**
+ * Render package.json file from template using provided parameters.
+ * @param {Object} params Map of parameter names to values
+ * @param {function(Error, string)} callback Callback to pass rendered template
+ *     text to
+ */
+function generatePackage(params, callback) {
+  fs.readFile(package_tpl_path, {encoding: 'utf-8'}, function(err, template) {
+    if (err) {
+      callback(err);
+    } else {
+      var rendered = Mustache.render(template, params);
+      callback(null, rendered);
+    }
+  });
+}
+
+/**
+ * Copy a file
+ * @param {string} src_path The filepath to copy from
+ * @param {string} dest_path The filepath to copy to
+ */
+function copyFile(src_path, dest_path) {
+  fs.createReadStream(src_path).pipe(fs.createWriteStream(dest_path));
+}
+
+/**
+ * Run the script. Copies the index.js and LICENSE files to the output path,
+ * renders the package.json template to the output path, and generates a
+ * service.json file from the input proto files using pbjs. The arguments are
+ * taken directly from the command line, and handled as follows:
+ * -i (--include) : An include path for pbjs (can be dpulicated)
+ * -o (--output): The output path
+ * -n (--name): The name of the package
+ * -v (--version): The package version
+ * @param {Array} argv The argument vector
+ */
+function main(argv) {
+  var args = parseArgs(argv, arg_format);
+  var out_path = path.resolve(args.out);
+  var include_dirs = [];
+  if (args.include) {
+    include_dirs = _.map(_.flatten([args.include]), function(p) {
+      return path.resolve(p);
+    });
+  }
+  args.grpc_version = package_json.version;
+  generatePackage(args, function(err, rendered) {
+    if (err) throw err;
+    fs.writeFile(path.join(out_path, 'package.json'), rendered, function(err) {
+      if (err) throw err;
+    });
+  });
+  copyFile(path.join(template_path, 'index.js'),
+           path.join(out_path, 'index.js'));
+  copyFile(path.join(__dirname, '..', 'LICENSE'),
+           path.join(out_path, 'LICENSE'));
+
+  var service_stream = fs.createWriteStream(path.join(out_path,
+                                                      'service.json'));
+  var pbjs_args = _.flatten(['node', 'pbjs',
+                             args._[0],
+                             '-legacy',
+                             _.map(include_dirs, function(dir) {
+                               return "-path=" + dir;
+                             })]);
+  var old_stdout = process.stdout;
+  process.__defineGetter__('stdout', function() {
+    return service_stream;
+  });
+  var pbjs_status = pbjs.main(pbjs_args);
+  process.__defineGetter__('stdout', function() {
+    return old_stdout;
+  });
+  if (pbjs_status !== pbjs.STATUS_OK) {
+    throw new Error('pbjs failed with status code ' + pbjs_status);
+  }
+}
+
+exports.main = main;
diff --git a/src/node/cli/service_packager/index.js b/src/node/cli/service_packager/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..811e08b89ac5eea2f754a77fb3ced883ddef45ee
--- /dev/null
+++ b/src/node/cli/service_packager/index.js
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+var grpc = require('grpc');
+exports.client = grpc.load(__dirname + '/service.json', 'json');
+exports.auth = require('google-auth-library');
diff --git a/src/node/cli/service_packager/package.json.template b/src/node/cli/service_packager/package.json.template
new file mode 100644
index 0000000000000000000000000000000000000000..9f9019172e0d1c3a471c6d4fe0743eed399c471d
--- /dev/null
+++ b/src/node/cli/service_packager/package.json.template
@@ -0,0 +1,17 @@
+{
+  "name": "{{{name}}}",
+  "version": "{{{version}}}",
+  "author": "Google Inc.",
+  "description": "Client library for {{{name}}} built on gRPC",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "grpc": "{{{grpc_version}}}",
+    "google-auth-library": "^0.9.2"
+  },
+  "main": "index.js",
+  "files": [
+    "LICENSE",
+    "index.js",
+    "service.json"
+  ]
+}
diff --git a/src/node/package.json b/src/node/package.json
index 8d413c3ffaafd88e223c9e0398a4ef1598b0ce00..3f31ba49ffe02d7874509cd9370b4b1bc5bf208f 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -36,6 +36,7 @@
     "jshint": "^2.5.0",
     "minimist": "^1.1.0",
     "mocha": "~1.21.0",
+    "mustache": "^2.0.0",
     "strftime": "^0.8.2"
   },
   "engines": {
@@ -46,6 +47,8 @@
     "README.md",
     "index.js",
     "binding.gyp",
+    "bin",
+    "cli",
     "examples",
     "ext",
     "interop",