diff --git a/src/node/.jshintrc b/src/node/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..8237e0d2b6430de7834f13db03a1fe2a01c76fa7
--- /dev/null
+++ b/src/node/.jshintrc
@@ -0,0 +1,28 @@
+{
+  "bitwise": true,
+  "curly": true,
+  "eqeqeq": true,
+  "esnext": true,
+  "freeze": true,
+  "immed": true,
+  "indent": 2,
+  "latedef": "nofunc",
+  "maxlen": 80,
+  "newcap": true,
+  "node": true,
+  "noarg": true,
+  "quotmark": "single",
+  "strict": true,
+  "trailing": true,
+  "undef": true,
+  "unused": "vars",
+  "globals": {
+    /* Mocha-provided globals */
+    "describe": false,
+    "it": false,
+    "before": false,
+    "beforeEach": false,
+    "after": false,
+    "afterEach": false
+  }
+}
diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js
index 89bc0de3ba0d0f9dcd09e8aa7e89108ad6960c9c..ae548c89e402abe08bc8822339a07c5d5e958fc1 100644
--- a/src/node/examples/math_server.js
+++ b/src/node/examples/math_server.js
@@ -31,9 +31,8 @@
  *
  */
 
-var _ = require('underscore');
-var ProtoBuf = require('protobufjs');
-var fs = require('fs');
+'use strict';
+
 var util = require('util');
 
 var Transform = require('stream').Transform;
diff --git a/src/node/examples/perf_test.js b/src/node/examples/perf_test.js
index c5e28727369e7095175ed142a721cb675ec0f690..31083e098727d37e4893d3fb2bcde3fb938e4bba 100644
--- a/src/node/examples/perf_test.js
+++ b/src/node/examples/perf_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var grpc = require('..');
 var testProto = grpc.load(__dirname + '/../interop/test.proto').grpc.testing;
 var _ = require('underscore');
@@ -44,7 +46,6 @@ function runTest(iterations, callback) {
   function runIterations(finish) {
     var start = process.hrtime();
     var intervals = [];
-    var pending = iterations;
     function next(i) {
       if (i >= iterations) {
         testServer.server.shutdown();
@@ -69,28 +70,30 @@ function runTest(iterations, callback) {
 
   function warmUp(num) {
     var pending = num;
+    function startCall() {
+      client.emptyCall({}, function(err, resp) {
+        pending--;
+        if (pending === 0) {
+          runIterations(callback);
+        }
+      });
+    }
     for (var i = 0; i < num; i++) {
-      (function(i) {
-        client.emptyCall({}, function(err, resp) {
-          pending--;
-          if (pending === 0) {
-            runIterations(callback);
-          }
-        });
-      })(i);
+      startCall();
     }
   }
   warmUp(100);
 }
 
-function percentile(arr, percentile) {
-  if (percentile > 99) {
-    percentile = 99;
+function percentile(arr, pct) {
+  if (pct > 99) {
+    pct = 99;
   }
-  if (percentile < 0) {
-    percentile = 0;
+  if (pct < 0) {
+    pct = 0;
   }
-  return arr[(arr.length * percentile / 100)|0];
+  var index = Math.floor(arr.length * pct / 100);
+  return arr[index];
 }
 
 if (require.main === module) {
diff --git a/src/node/examples/stock_server.js b/src/node/examples/stock_server.js
index b226a7157320fbb5a327b152daa843db59675c72..e475c9cb4ccff0907cf305d6aa194eabd38991bf 100644
--- a/src/node/examples/stock_server.js
+++ b/src/node/examples/stock_server.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var _ = require('underscore');
 var grpc = require('..');
 var examples = grpc.load(__dirname + '/stock.proto').examples;
diff --git a/src/node/index.js b/src/node/index.js
index 1bef2072ddea82d797b6934eb6e55238f3da5844..4b5302e4382a7edeb02bd6b727e5f6fda53a5878 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var _ = require('underscore');
 
 var ProtoBuf = require('protobufjs');
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index fc2fdf4dc9d38b2f294f3b27588a87b16cc617df..eaf254bcfef0cd493996f87194384148053126cd 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var fs = require('fs');
 var path = require('path');
 var grpc = require('..');
@@ -41,7 +43,8 @@ var assert = require('assert');
 
 var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
 var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
-var AUTH_USER = '155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk@developer.gserviceaccount.com';
+var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
+    '@developer.gserviceaccount.com');
 
 /**
  * Create a buffer filled with size zeroes
@@ -318,7 +321,7 @@ var test_cases = {
 /**
  * Execute a single test case.
  * @param {string} address The address of the server to connect to, in the
- *     format "hostname:port"
+ *     format 'hostname:port'
  * @param {string} host_overrirde The hostname of the server to use as an SSL
  *     override
  * @param {string} test_case The name of the test case to run
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index c97d23445504dcbfefddf31b8eb495ebd71b4465..125ede174642f05bb0ee5f3d0831f5b69b797d7c 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var fs = require('fs');
 var path = require('path');
 var _ = require('underscore');
diff --git a/src/node/package.json b/src/node/package.json
index 642d80e26f0c654b1b53d229edc75eeb01d2a790..bbd89be77d70a213b167360dd846dc246af69649 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -3,10 +3,12 @@
   "version": "0.2.0",
   "description": "gRPC Library for Node",
   "scripts": {
-    "test": "./node_modules/mocha/bin/mocha"
+    "lint": "jshint src test examples interop index.js",
+    "test": "./node_modules/mocha/bin/mocha && npm run-script lint"
   },
   "dependencies": {
     "bindings": "^1.2.1",
+    "jshint": "^2.5.5",
     "nan": "~1.3.0",
     "protobufjs": "murgatroid99/ProtoBuf.js",
     "underscore": "^1.7.0",
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 19c3144c7d96c5890e72686ae267319ffbfd0896..aaa7be79c9d4898adba04d1f131afa04b7bd7eaa 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var _ = require('underscore');
 
 var capitalize = require('underscore.string/capitalize');
@@ -77,6 +79,7 @@ function ClientWritableStream(call, serialize) {
  * @param {function(Error=)} callback Called when the write is complete
  */
 function _write(chunk, encoding, callback) {
+  /* jshint validthis: true */
   var batch = {};
   batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk);
   this.call.startBatch(batch, function(err, event) {
@@ -85,7 +88,7 @@ function _write(chunk, encoding, callback) {
     }
     callback();
   });
-};
+}
 
 ClientWritableStream.prototype._write = _write;
 
@@ -111,6 +114,7 @@ function ClientReadableStream(call, deserialize) {
  * @param {*} size Ignored because we use objectMode=true
  */
 function _read(size) {
+  /* jshint validthis: true */
   var self = this;
   /**
    * Callback to be called when a READ event is received. Pushes the data onto
@@ -126,7 +130,7 @@ function _read(size) {
       return;
     }
     var data = event.read;
-    if (self.push(self.deserialize(data)) && data != null) {
+    if (self.push(self.deserialize(data)) && data !== null) {
       var read_batch = {};
       read_batch[grpc.opType.RECV_MESSAGE] = true;
       self.call.startBatch(read_batch, readCallback);
@@ -144,7 +148,7 @@ function _read(size) {
       self.call.startBatch(read_batch, readCallback);
     }
   }
-};
+}
 
 ClientReadableStream.prototype._read = _read;
 
@@ -163,10 +167,6 @@ function ClientDuplexStream(call, serialize, deserialize) {
   Duplex.call(this, {objectMode: true});
   this.serialize = common.wrapIgnoreNull(serialize);
   this.deserialize = common.wrapIgnoreNull(deserialize);
-  var self = this;
-  var finished = false;
-  // Indicates that a read is currently pending
-  var reading = false;
   this.call = call;
   this.on('finish', function() {
     var batch = {};
@@ -182,6 +182,7 @@ ClientDuplexStream.prototype._write = _write;
  * Cancel the ongoing call
  */
 function cancel() {
+  /* jshint validthis: true */
   this.call.cancel();
 }
 
@@ -213,6 +214,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
    * @return {EventEmitter} An event emitter for stream related events
    */
   function makeUnaryRequest(argument, callback, metadata, deadline) {
+    /* jshint validthis: true */
     if (deadline === undefined) {
       deadline = Infinity;
     }
@@ -242,7 +244,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
           callback(err);
           return;
         }
-        if (response.status.code != grpc.status.OK) {
+        if (response.status.code !== grpc.status.OK) {
           callback(response.status);
           return;
         }
@@ -278,6 +280,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
    * @return {EventEmitter} An event emitter for stream related events
    */
   function makeClientStreamRequest(callback, metadata, deadline) {
+    /* jshint validthis: true */
     if (deadline === undefined) {
       deadline = Infinity;
     }
@@ -310,7 +313,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
           callback(err);
           return;
         }
-        if (response.status.code != grpc.status.OK) {
+        if (response.status.code !== grpc.status.OK) {
           callback(response.status);
           return;
         }
@@ -345,6 +348,7 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
    * @return {EventEmitter} An event emitter for stream related events
    */
   function makeServerStreamRequest(argument, metadata, deadline) {
+    /* jshint validthis: true */
     if (deadline === undefined) {
       deadline = Infinity;
     }
@@ -404,6 +408,7 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
    * @return {EventEmitter} An event emitter for stream related events
    */
   function makeBidiStreamRequest(metadata, deadline) {
+    /* jshint validthis: true */
     if (deadline === undefined) {
       deadline = Infinity;
     }
diff --git a/src/node/src/common.js b/src/node/src/common.js
index 848c96742d958dc233420fa9fdae861ac8aa6c99..eec8f0f9878f7f4fa1974d785b0566e55e235e71 100644
--- a/src/node/src/common.js
+++ b/src/node/src/common.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var _ = require('underscore');
 
 var capitalize = require('underscore.string/capitalize');
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 48c349ef99d0a2f56e474b11e35f5fdd2f633c4d..91dde0225181cc9341fd454bbab111723493c313 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var _ = require('underscore');
 
 var capitalize = require('underscore.string/capitalize');
@@ -217,6 +219,7 @@ function ServerWritableStream(call, serialize) {
  *     complete
  */
 function _write(chunk, encoding, callback) {
+  /* jshint validthis: true */
   var batch = {};
   batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk);
   this.call.startBatch(batch, function(err, value) {
@@ -251,6 +254,7 @@ function ServerReadableStream(call, deserialize) {
  * @param {number} size Ignored
  */
 function _read(size) {
+  /* jshint validthis: true */
   var self = this;
   /**
    * Callback to be called when a READ event is received. Pushes the data onto
@@ -267,7 +271,7 @@ function _read(size) {
       return;
     }
     var data = event.read;
-    if (self.push(self.deserialize(data)) && data != null) {
+    if (self.push(self.deserialize(data)) && data !== null) {
       var read_batch = {};
       read_batch[grpc.opType.RECV_MESSAGE] = true;
       self.call.startBatch(read_batch, readCallback);
@@ -424,7 +428,6 @@ function Server(getMetadata, options) {
   var handlers = this.handlers;
   var server = new grpc.Server(options);
   this._server = server;
-  var started = false;
   /**
    * Start the server and begin handling requests
    * @this Server
@@ -456,8 +459,7 @@ function Server(getMetadata, options) {
         return;
       }
       server.requestCall(handleNewCall);
-      var handler = undefined;
-      var deadline = details.deadline;
+      var handler;
       if (handlers.hasOwnProperty(method)) {
         handler = handlers[method];
       } else {
@@ -465,7 +467,7 @@ function Server(getMetadata, options) {
         batch[grpc.opType.SEND_INITIAL_METADATA] = {};
         batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
           code: grpc.status.UNIMPLEMENTED,
-          details: "This method is not available on this server.",
+          details: 'This method is not available on this server.',
           metadata: {}
         };
         batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index c1a7e95fa09ab8ae8f9737715720d9eea405cdcb..7b2b36ae3710add87bcaa6f6d03fe1003bdac167 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var assert = require('assert');
 var grpc = require('bindings')('grpc.node');
 
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index 449a8cc4c362c12b3e2abefd8ba1ba0b86db5e8b..33200c99ee2d8f3305d9efa703c2cbd28ddf4ea4 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var assert = require('assert');
 var grpc = require('bindings')('grpc.node');
 
diff --git a/src/node/test/constant_test.js b/src/node/test/constant_test.js
index 4a403868c7c6957a2f5c84b95b6e8746514ccb42..ecc98ec44380942858ec8012451c7c32055bd43b 100644
--- a/src/node/test/constant_test.js
+++ b/src/node/test/constant_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var assert = require('assert');
 var grpc = require('bindings')('grpc.node');
 
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index 8e99d6f1628016171ea449c0a052fad7eb284446..1cc192869175032399f334a501dc84f6ba0e2ad0 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var assert = require('assert');
 var grpc = require('bindings')('grpc.node');
 
@@ -227,7 +229,7 @@ describe('end-to-end', function() {
         response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
         server_call.startBatch(response_batch, function(err, response) {
           assert(response['send status']);
-          assert(!response['cancelled']);
+          assert(!response.cancelled);
           done();
         });
       });
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index d1bdd1660f0a5889f0033ab0a2612b6cd0be8497..8dc933eac563d072c176f64ba27546ebe6b2e5c6 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var interop_server = require('../interop/interop_server.js');
 var interop_client = require('../interop/interop_client.js');
 
diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js
index fd946e0325de6a761f986dc5064bd4a3e174862b..d83f64116f71672b2ee23f3b32c1fc8df04e12d2 100644
--- a/src/node/test/math_client_test.js
+++ b/src/node/test/math_client_test.js
@@ -31,6 +31,8 @@
  *
  */
 
+'use strict';
+
 var assert = require('assert');
 
 var grpc = require('..');
@@ -59,7 +61,7 @@ describe('Math client', function() {
   });
   it('should handle a single request', function(done) {
     var arg = {dividend: 7, divisor: 4};
-    var call = math_client.div(arg, function handleDivResult(err, value) {
+    math_client.div(arg, function handleDivResult(err, value) {
       assert.ifError(err);
       assert.equal(value.quotient, 1);
       assert.equal(value.remainder, 3);
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index d6694724e5498d326d5edc30ebd32a3c08a60c31..91d8197bee1663b2379078e9c1835e0a9adc21d8 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -31,9 +31,9 @@
  *
  */
 
-var assert = require('assert');
+'use strict';
 
-var surface_server = require('../src/server.js');
+var assert = require('assert');
 
 var surface_client = require('../src/client.js');