diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp
index a379ebd80a..0fd8ff595f 100644
--- a/libraries/animation/src/AnimSkeleton.cpp
+++ b/libraries/animation/src/AnimSkeleton.cpp
@@ -228,9 +228,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
     }
 }
 
-#ifndef NDEBUG
-#define DUMP_FBX_JOINTS
-void AnimSkeleton::dump() const {
+void AnimSkeleton::dump(bool verbose) const {
     qCDebug(animation) << "[";
     for (int i = 0; i < getNumJoints(); i++) {
         qCDebug(animation) << "    {";
@@ -240,24 +238,24 @@ void AnimSkeleton::dump() const {
         qCDebug(animation) << "        relBindPose =" << getRelativeBindPose(i);
         qCDebug(animation) << "        absDefaultPose =" << getAbsoluteDefaultPose(i);
         qCDebug(animation) << "        relDefaultPose =" << getRelativeDefaultPose(i);
-#ifdef DUMP_FBX_JOINTS
-        qCDebug(animation) << "        fbxJoint =";
-        qCDebug(animation) << "            isFree =" << _joints[i].isFree;
-        qCDebug(animation) << "            freeLineage =" << _joints[i].freeLineage;
-        qCDebug(animation) << "            parentIndex =" << _joints[i].parentIndex;
-        qCDebug(animation) << "            translation =" << _joints[i].translation;
-        qCDebug(animation) << "            preTransform =" << _joints[i].preTransform;
-        qCDebug(animation) << "            preRotation =" << _joints[i].preRotation;
-        qCDebug(animation) << "            rotation =" << _joints[i].rotation;
-        qCDebug(animation) << "            postRotation =" << _joints[i].postRotation;
-        qCDebug(animation) << "            postTransform =" << _joints[i].postTransform;
-        qCDebug(animation) << "            transform =" << _joints[i].transform;
-        qCDebug(animation) << "            rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax;
-        qCDebug(animation) << "            inverseDefaultRotation" << _joints[i].inverseDefaultRotation;
-        qCDebug(animation) << "            inverseBindRotation" << _joints[i].inverseBindRotation;
-        qCDebug(animation) << "            bindTransform" << _joints[i].bindTransform;
-        qCDebug(animation) << "            isSkeletonJoint" << _joints[i].isSkeletonJoint;
-#endif
+        if (verbose) {
+            qCDebug(animation) << "        fbxJoint =";
+            qCDebug(animation) << "            isFree =" << _joints[i].isFree;
+            qCDebug(animation) << "            freeLineage =" << _joints[i].freeLineage;
+            qCDebug(animation) << "            parentIndex =" << _joints[i].parentIndex;
+            qCDebug(animation) << "            translation =" << _joints[i].translation;
+            qCDebug(animation) << "            preTransform =" << _joints[i].preTransform;
+            qCDebug(animation) << "            preRotation =" << _joints[i].preRotation;
+            qCDebug(animation) << "            rotation =" << _joints[i].rotation;
+            qCDebug(animation) << "            postRotation =" << _joints[i].postRotation;
+            qCDebug(animation) << "            postTransform =" << _joints[i].postTransform;
+            qCDebug(animation) << "            transform =" << _joints[i].transform;
+            qCDebug(animation) << "            rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax;
+            qCDebug(animation) << "            inverseDefaultRotation" << _joints[i].inverseDefaultRotation;
+            qCDebug(animation) << "            inverseBindRotation" << _joints[i].inverseBindRotation;
+            qCDebug(animation) << "            bindTransform" << _joints[i].bindTransform;
+            qCDebug(animation) << "            isSkeletonJoint" << _joints[i].isSkeletonJoint;
+        }
         if (getParentIndex(i) >= 0) {
             qCDebug(animation) << "        parent =" << getJointName(getParentIndex(i));
         }
@@ -284,4 +282,4 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const {
     }
     qCDebug(animation) << "]";
 }
-#endif
+
diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h
index e1c6ae95c8..f588c14f90 100644
--- a/libraries/animation/src/AnimSkeleton.h
+++ b/libraries/animation/src/AnimSkeleton.h
@@ -63,10 +63,8 @@ public:
     void mirrorRelativePoses(AnimPoseVec& poses) const;
     void mirrorAbsolutePoses(AnimPoseVec& poses) const;
 
-#ifndef NDEBUG
-    void dump() const;
+    void dump(bool verbose) const;
     void dump(const AnimPoseVec& poses) const;
-#endif
 
 protected:
     void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index cf0e25a757..a85a112bf5 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -13,3 +13,7 @@ set_target_properties(ice-client PROPERTIES FOLDER "Tools")
 
 add_subdirectory(ac-client)
 set_target_properties(ac-client PROPERTIES FOLDER "Tools")
+
+add_subdirectory(skeleton-dump)
+set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools")
+
diff --git a/tools/skeleton-dump/CMakeLists.txt b/tools/skeleton-dump/CMakeLists.txt
new file mode 100644
index 0000000000..04d450d9c2
--- /dev/null
+++ b/tools/skeleton-dump/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(TARGET_NAME skeleton-dump)
+setup_hifi_project(Core Widgets)
+link_hifi_libraries(shared fbx model gpu gl animation)
+
diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp
new file mode 100644
index 0000000000..e9d8243e38
--- /dev/null
+++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp
@@ -0,0 +1,63 @@
+//
+//  SkeletonDumpApp.cpp
+//  tools/skeleton-dump/src
+//
+//  Created by Anthony Thibault on 11/4/16.
+//  Copyright 2016 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#include "SkeletonDumpApp.h"
+#include <QCommandLineParser>
+#include <QFile>
+#include <FBXReader.h>
+#include <AnimSkeleton.h>
+
+SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) {
+
+    // parse command-line
+    QCommandLineParser parser;
+    parser.setApplicationDescription("High Fidelity FBX Skeleton Analyzer");
+    const QCommandLineOption helpOption = parser.addHelpOption();
+
+    const QCommandLineOption verboseOutput("v", "verbose output");
+    parser.addOption(verboseOutput);
+
+    const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx");
+    parser.addOption(inputFilenameOption);
+
+    if (!parser.parse(QCoreApplication::arguments())) {
+        qCritical() << parser.errorText() << endl;
+        parser.showHelp();
+        _returnCode = 1;
+        return;
+    }
+
+    if (parser.isSet(helpOption)) {
+        parser.showHelp();
+        return;
+    }
+
+    bool verbose = parser.isSet(verboseOutput);
+
+    QString inputFilename;
+    if (parser.isSet(inputFilenameOption)) {
+        inputFilename = parser.value(inputFilenameOption);
+    }
+
+    QFile file(inputFilename);
+    if (!file.open(QIODevice::ReadOnly)) {
+        qCritical() << "Failed to open file " << inputFilename;
+        _returnCode = 2;
+        return;
+    }
+    QByteArray blob = file.readAll();
+    std::unique_ptr<FBXGeometry> fbxGeometry(readFBX(blob, QVariantHash()));
+    std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*fbxGeometry));
+    skeleton->dump(verbose);
+}
+
+SkeletonDumpApp::~SkeletonDumpApp() {
+}
diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h
new file mode 100644
index 0000000000..40df98eb65
--- /dev/null
+++ b/tools/skeleton-dump/src/SkeletonDumpApp.h
@@ -0,0 +1,29 @@
+//
+//  SkeletonDumpApp.h
+//  tools/skeleton-dump/src
+//
+//  Created by Anthony Thibault on 11/4/16.
+//  Copyright 2016 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_SkeletonDumpApp_h
+#define hifi_SkeletonDumpApp_h
+
+#include <QApplication>
+
+class SkeletonDumpApp : public QCoreApplication {
+    Q_OBJECT
+public:
+    SkeletonDumpApp(int argc, char* argv[]);
+    ~SkeletonDumpApp();
+
+    int getReturnCode() const { return _returnCode; }
+
+private:
+    int _returnCode { 0 };
+};
+
+#endif //hifi_SkeletonDumpApp_h
diff --git a/tools/skeleton-dump/src/main.cpp b/tools/skeleton-dump/src/main.cpp
new file mode 100644
index 0000000000..6cf4d41f31
--- /dev/null
+++ b/tools/skeleton-dump/src/main.cpp
@@ -0,0 +1,22 @@
+//
+//  main.cpp
+//  tools/skeleton-dump/src
+//
+//  Created by Anthony Thibault on 11/4/16.
+//  Copyright 2016 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+#include <QDebug>
+
+#include "SkeletonDumpApp.h"
+
+int main(int argc, char * argv[]) {
+    SkeletonDumpApp app(argc, argv);
+    return app.getReturnCode();
+}