diff --git a/capitanodoc.ts b/capitanodoc.ts
new file mode 100644
index 00000000..9cda44b9
--- /dev/null
+++ b/capitanodoc.ts
@@ -0,0 +1,114 @@
+export = {
+	title: 'Resin CLI Documentation',
+	introduction: `\
+This tool allows you to interact with the resin.io api from the comfort of your command line.
+
+Please make sure your system meets the requirements as specified in the [README](https://github.com/resin-io/resin-cli).
+
+To get started download the CLI from npm.
+
+	$ npm install resin-cli -g
+
+Then authenticate yourself:
+
+	$ resin login
+
+Now you have access to all the commands referenced below.
+
+## Proxy support
+
+The CLI does support HTTP(S) proxies.
+
+You can configure the proxy using several methods (in order of their precedence):
+
+* set the \`RESINRC_PROXY\` environment variable in the URL format (with protocol, host, port, and optionally the basic auth),
+* use the [resin config file](https://www.npmjs.com/package/resin-settings-client#documentation) (project-specific or user-level)
+and set the \`proxy\` setting. This can be:
+	* a string in the URL format,
+	* or an object following [this format](https://www.npmjs.com/package/global-tunnel-ng#options), which allows more control,
+* or set the conventional \`https_proxy\` / \`HTTPS_PROXY\` / \`http_proxy\` / \`HTTP_PROXY\`
+environment variable (in the same standard URL format).\
+`,
+
+	categories: [
+		{
+			title: 'Application',
+			files: [ 'build/actions/app.js' ]
+		},
+		{
+			title: 'Authentication',
+			files: [ 'build/actions/auth.js' ]
+		},
+		{
+			title: 'Device',
+			files: [ 'build/actions/device.js' ]
+		},
+		{
+			title: 'Environment Variables',
+			files: [ 'build/actions/environment-variables.js' ]
+		},
+		{
+			title: 'Help',
+			files: [ 'build/actions/help.js' ]
+		},
+		{
+			title: 'Information',
+			files: [ 'build/actions/info.js' ]
+		},
+		{
+			title: 'Keys',
+			files: [ 'build/actions/keys.js' ]
+		},
+		{
+			title: 'Logs',
+			files: [ 'build/actions/logs.js' ]
+		},
+		{
+			title: 'Sync',
+			files: [ 'build/actions/sync.js' ]
+		},
+		{
+			title: 'SSH',
+			files: [ 'build/actions/ssh.js' ]
+		},
+		{
+			title: 'Notes',
+			files: [ 'build/actions/notes.js' ]
+		},
+		{
+			title: 'OS',
+			files: [ 'build/actions/os.js' ]
+		},
+		{
+			title: 'Config',
+			files: [ 'build/actions/config.js' ]
+		},
+		{
+			title: 'Preload',
+			files: [ 'build/actions/preload.js' ]
+		},
+		{
+			title: 'Settings',
+			files: [ 'build/actions/settings.js' ]
+		},
+		{
+			title: 'Wizard',
+			files: [ 'build/actions/wizard.js' ]
+		},
+		{
+			title: 'Local',
+			files: [ 'build/actions/local/index.js' ]
+		},
+		{
+			title: 'Deploy',
+			files: [
+				'build/actions/build.js',
+				'build/actions/deploy.js'
+			]
+		},
+		{
+			title: 'Utilities',
+			files: [ 'build/actions/util.js' ]
+		},
+	]
+};
diff --git a/doc/cli.markdown b/doc/cli.markdown
index 3cb7a2cc..9caea2f0 100644
--- a/doc/cli.markdown
+++ b/doc/cli.markdown
@@ -254,7 +254,7 @@ web-based login
 
 credential-based login
 
-#### --email, --e,u, --e,u <email>
+#### --email, -e, -u <email>
 
 email
 
@@ -310,7 +310,7 @@ Examples:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -464,7 +464,7 @@ Examples:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -482,7 +482,7 @@ Examples:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -529,7 +529,7 @@ Example:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -589,7 +589,7 @@ Examples:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -845,7 +845,7 @@ Examples:
 
 ### Options
 
-#### --device, --d,dev, --d,dev <device>
+#### --device, -d, --dev <device>
 
 device uuid
 
@@ -937,7 +937,7 @@ Examples:
 
 show advanced configuration options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
@@ -1081,7 +1081,7 @@ Examples:
 
 ### Options
 
-#### --application, --a,app, --a,app <application>
+#### --application, -a, --app <application>
 
 application name
 
diff --git a/extras/capitanodoc/doc-types.d.ts b/extras/capitanodoc/doc-types.d.ts
new file mode 100644
index 00000000..536cf6c8
--- /dev/null
+++ b/extras/capitanodoc/doc-types.d.ts
@@ -0,0 +1,14 @@
+import { CommandDefinition } from 'capitano';
+
+export interface Document {
+	title: string;
+	introduction: string;
+	categories: Category[];
+}
+
+export interface Category {
+	title: string;
+	commands: CommandDefinition[];
+}
+
+export { CommandDefinition as Command };
diff --git a/extras/capitanodoc/index.coffee b/extras/capitanodoc/index.coffee
deleted file mode 100644
index c2f2223b..00000000
--- a/extras/capitanodoc/index.coffee
+++ /dev/null
@@ -1,46 +0,0 @@
-_ = require('lodash')
-path = require('path')
-capitanodoc = require('../../capitanodoc')
-markdown = require('./markdown')
-
-result = {}
-result.title = capitanodoc.title
-result.introduction = capitanodoc.introduction
-result.categories = []
-
-for commandCategory in capitanodoc.categories
-	category = {}
-	category.title = commandCategory.title
-	category.commands = []
-
-	for file in commandCategory.files
-		actions = require(path.join(process.cwd(), file))
-
-		if actions.signature?
-			category.commands.push(_.omit(actions, 'action'))
-		else
-			for actionName, actionCommand of actions
-				category.commands.push(_.omit(actionCommand, 'action'))
-
-	result.categories.push(category)
-
-result.toc = _.cloneDeep(result.categories)
-result.toc = _.map result.toc, (category) ->
-	category.commands = _.map category.commands, (command) ->
-		return {
-			signature: command.signature
-			anchor: '#' + command.signature
-								.replace(/\s/g,'-')
-								.replace(/</g, '60-')
-								.replace(/>/g, '-62-')
-								.replace(/\[/g, '')
-								.replace(/\]/g, '-')
-								.replace(/--/g, '-')
-								.replace(/\.\.\./g, '')
-								.replace(/\|/g, '')
-								.toLowerCase()
-		}
-
-	return category
-
-console.log(markdown.display(result))
diff --git a/extras/capitanodoc/index.ts b/extras/capitanodoc/index.ts
new file mode 100644
index 00000000..4346a41a
--- /dev/null
+++ b/extras/capitanodoc/index.ts
@@ -0,0 +1,33 @@
+import capitanodoc = require('../../capitanodoc');
+import * as _ from 'lodash';
+import * as path from 'path';
+import * as markdown from './markdown';
+import { Document, Category } from './doc-types';
+
+const result = <Document> {};
+result.title = capitanodoc.title;
+result.introduction = capitanodoc.introduction;
+result.categories = [];
+
+for (let commandCategory of capitanodoc.categories) {
+	const category = <Category> {};
+	category.title = commandCategory.title;
+	category.commands = [];
+
+	for (let file of commandCategory.files) {
+		const actions: any = require(path.join(process.cwd(), file));
+
+		if (actions.signature != null) {
+			category.commands.push(_.omit(actions, 'action'));
+		} else {
+			for (let actionName in actions) {
+				const actionCommand = actions[actionName];
+				category.commands.push(_.omit(actionCommand, 'action'));
+			}
+		}
+	}
+
+	result.categories.push(category);
+}
+
+console.log(markdown.render(result));
diff --git a/extras/capitanodoc/markdown.coffee b/extras/capitanodoc/markdown.coffee
deleted file mode 100644
index 85c0d6e1..00000000
--- a/extras/capitanodoc/markdown.coffee
+++ /dev/null
@@ -1,66 +0,0 @@
-_ = require('lodash')
-ent = require('ent')
-utils = require('./utils')
-
-exports.command = (command) ->
-	result = """
-		## #{ent.encode(command.signature)}
-
-		#{command.help}\n
-	"""
-
-	if not _.isEmpty(command.options)
-		result += '\n### Options'
-
-		for option in command.options
-			result += """
-				\n\n#### #{utils.parseSignature(option)}
-
-				#{option.description}
-			"""
-
-		result += '\n'
-
-	return result
-
-exports.category = (category) ->
-	result = """
-		# #{category.title}\n
-	"""
-
-	for command in category.commands
-		result += '\n' + exports.command(command)
-
-	return result
-
-exports.toc = (toc) ->
-	result = '''
-		# Table of contents\n
-	'''
-
-	for category in toc
-
-		result += """
-			\n- #{category.title}\n\n
-		"""
-
-		for command in category.commands
-			result += """
-				\t- [#{ent.encode(command.signature)}](#{command.anchor})\n
-			"""
-
-	return result
-
-exports.display = (doc) ->
-	result = """
-		# #{doc.title}
-
-		#{doc.introduction}
-
-		#{exports.toc(doc.toc)}
-	"""
-
-	for category in doc.categories
-		result += '\n' + exports.category(category)
-
-	return result
diff --git a/extras/capitanodoc/markdown.ts b/extras/capitanodoc/markdown.ts
new file mode 100644
index 00000000..6a272d1b
--- /dev/null
+++ b/extras/capitanodoc/markdown.ts
@@ -0,0 +1,90 @@
+import * as _ from 'lodash';
+import * as ent from 'ent';
+import * as utils from './utils';
+import { Document, Category, Command } from './doc-types';
+
+export function renderCommand(command: Command) {
+	let result = `\
+## ${ent.encode(command.signature)}
+
+${command.help}\n\
+`;
+
+	if (!_.isEmpty(command.options)) {
+		result += '\n### Options';
+
+		for (let option of command.options!) {
+			result += `\
+\n\n#### ${utils.parseSignature(option)}
+
+${option.description}\
+`;
+		}
+
+		result += '\n';
+	}
+
+	return result;
+};
+
+export function renderCategory(category: Category) {
+	let result = `\
+# ${category.title}\n\
+`;
+
+	for (let command of category.commands) {
+		result += `\n${renderCommand(command)}`;
+	}
+
+	return result;
+};
+
+function getAnchor(command: Command) {
+	return '#' + command.signature
+		.replace(/\s/g,'-')
+		.replace(/</g, '60-')
+		.replace(/>/g, '-62-')
+		.replace(/\[/g, '')
+		.replace(/\]/g, '-')
+		.replace(/--/g, '-')
+		.replace(/\.\.\./g, '')
+		.replace(/\|/g, '')
+		.toLowerCase();
+}
+
+export function renderToc(categories: Category[]) {
+	let result = `\
+# Table of contents\n\
+`;
+
+	for (let category of categories) {
+
+		result += `\
+\n- ${category.title}\n\n\
+`;
+
+		for (let command of category.commands) {
+			result += `\
+\t- [${ent.encode(command.signature)}](${getAnchor(command)})\n\
+`;
+		}
+	}
+
+	return result;
+};
+
+export function render(doc: Document) {
+	let result = `\
+# ${doc.title}
+
+${doc.introduction}
+
+${renderToc(doc.categories)}\
+`;
+
+	for (let category of doc.categories) {
+		result += `\n${renderCategory(category)}`;
+	}
+
+	return result;
+};
diff --git a/extras/capitanodoc/utils.coffee b/extras/capitanodoc/utils.coffee
deleted file mode 100644
index 84eac0dc..00000000
--- a/extras/capitanodoc/utils.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-_ = require('lodash')
-ent = require('ent')
-
-exports.getOptionPrefix = (signature) ->
-	if signature.length > 1
-		return '--'
-	else
-		return '-'
-
-exports.getOptionSignature = (signature) ->
-	return "#{exports.getOptionPrefix(signature)}#{signature}"
-
-exports.parseSignature = (option) ->
-	result = exports.getOptionSignature(option.signature)
-
-	if not _.isEmpty(option.alias)
-		if _.isString(option.alias)
-			result += ", #{exports.getOptionSignature(option.alias)}"
-		else
-			for alias in option.alias
-				result += ", #{exports.getOptionSignature(option.alias)}"
-
-	if option.parameter?
-		result += " <#{option.parameter}>"
-
-	return ent.encode(result)
diff --git a/extras/capitanodoc/utils.ts b/extras/capitanodoc/utils.ts
new file mode 100644
index 00000000..bda4c343
--- /dev/null
+++ b/extras/capitanodoc/utils.ts
@@ -0,0 +1,35 @@
+import { OptionDefinition } from 'capitano';
+import * as _ from 'lodash';
+import * as ent from 'ent';
+
+export function getOptionPrefix(signature: string) {
+	if (signature.length > 1) {
+		return '--';
+	} else {
+		return '-';
+	}
+};
+
+export function getOptionSignature(signature: string) {
+	return `${getOptionPrefix(signature)}${signature}`;
+}
+
+export function parseSignature(option: OptionDefinition) {
+	let result = getOptionSignature(option.signature);
+
+	if (!_.isEmpty(option.alias)) {
+		if (_.isString(option.alias)) {
+			result += `, ${getOptionSignature(option.alias)}`;
+		} else {
+			for (let alias of option.alias!) {
+				result += `, ${getOptionSignature(alias)}`;
+			}
+		}
+	}
+
+	if (option.parameter != null) {
+		result += ` <${option.parameter}>`;
+	}
+
+	return ent.encode(result);
+};
diff --git a/extras/tsconfig.json b/extras/tsconfig.json
new file mode 100644
index 00000000..2fbc2f6e
--- /dev/null
+++ b/extras/tsconfig.json
@@ -0,0 +1,17 @@
+{
+	"compilerOptions": {
+		"module": "commonjs",
+		"target": "es5",
+		"outDir": "build",
+		"strict": true,
+		"noUnusedLocals": true,
+		"noUnusedParameters": true,
+		"preserveConstEnums": true,
+		"removeComments": true,
+		"sourceMap": true
+	},
+	"include": [
+		"../typings/*.d.ts",
+		"./**/*.ts"
+	]
+}
diff --git a/lib/actions/info.ts b/lib/actions/info.ts
index c55e74b5..f9ed173f 100644
--- a/lib/actions/info.ts
+++ b/lib/actions/info.ts
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { Command } from "capitano";
+import { CommandDefinition } from "capitano";
 
-export const version: Command = {
+export const version: CommandDefinition = {
 	signature: 'version',
 	description: 'output the version number',
 	help: `\
diff --git a/lib/actions/settings.ts b/lib/actions/settings.ts
index 5981cd30..1832a06c 100644
--- a/lib/actions/settings.ts
+++ b/lib/actions/settings.ts
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { Command } from "capitano";
+import { CommandDefinition } from "capitano";
 
-export const list: Command = {
+export const list: CommandDefinition = {
 	signature: 'settings',
 	description: 'print current settings',
 	help: `\
diff --git a/package.json b/package.json
index 65258af4..7315b653 100644
--- a/package.json
+++ b/package.json
@@ -31,13 +31,13 @@
   "scripts": {
     "prebuild": "rimraf build/ build-bin/ build-zip/",
     "build": "npm run build:src && npm run build:bin",
-    "build:src": "gulp build && tsc && npm run doc",
+    "build:src": "gulp build && tsc && npm run build:doc",
+    "build:doc": "mkdirp doc/ && ts-node extras/capitanodoc/index.ts > doc/cli.markdown",
     "build:bin": "ts-node --type-check -P automation automation/build-bin.ts",
     "release": "npm run build && ts-node --type-check -P automation automation/deploy-bin.ts",
     "pretest": "npm run build",
     "test": "gulp test",
     "ci": "npm run test && catch-uncommitted",
-    "doc": "mkdirp doc/ && coffee extras/capitanodoc/index.coffee > doc/cli.markdown",
     "watch": "gulp watch",
     "lint": "gulp lint",
     "prepublish": "require-npm4-to-publish",
diff --git a/typings/capitano.d.ts b/typings/capitano.d.ts
index 25e33697..e1c63547 100644
--- a/typings/capitano.d.ts
+++ b/typings/capitano.d.ts
@@ -7,7 +7,7 @@ declare module 'capitano' {
 		global: {};
 	}
 
-	export interface CommandOption {
+	export interface OptionDefinition {
 		signature: string;
 		description: string;
 		parameter?: string;
@@ -15,22 +15,39 @@ declare module 'capitano' {
 		alias?: string | string[];
 	}
 
-	export interface Command<P = {}, O = {}> {
+	export interface CommandDefinition<P = {}, O = {}> {
 		signature: string;
 		description: string;
 		help: string;
-		options?: CommandOption[],
+		options?: OptionDefinition[],
 		permission?: 'user',
 		action(params: P, options: O, done: () => void): void;
 	}
 
-	export interface BuiltCommand {
-		signature: {}
+	export interface Command {
+		signature: Signature;
+		options: Option[];
+		isWildcard(): boolean;
 	}
 
-	export function command(command: Command): void;
+	export interface Signature {
+		hasParameters(): boolean;
+		hasVariadicParameters(): boolean;
+		isWildcard(): boolean;
+		allowsStdin(): boolean;
+	}
+
+	export interface Option {
+		signature: Signature;
+		alias: string | string[];
+		boolean: boolean;
+		parameter: string;
+		required: boolean | string;
+	}
+
+	export function command(command: CommandDefinition): void;
 
 	export const state: {
-		getMatchCommand: (signature: string, callback: (e: Error, cmd: BuiltCommand) => void) => void
+		getMatchCommand: (signature: string, callback: (e: Error, cmd: Command) => void) => void
 	};
 }