diff --git a/bin/xlsx2csv.njs b/bin/xlsx2csv.njs
index 4de67cd..359d0cc 100755
--- a/bin/xlsx2csv.njs
+++ b/bin/xlsx2csv.njs
@@ -1,5 +1,5 @@
#!/usr/bin/env node
-
+/* xlsx.js (C) 2013 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
var XLSX = require('../');
var fs = require('fs'), program = require('commander');
diff --git a/bits/00_header.js b/bits/00_header.js
index 83d0233..9d0e29e 100644
--- a/bits/00_header.js
+++ b/bits/00_header.js
@@ -1,2 +1,3 @@
+/* xlsx.js (C) 2013 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint eqnull:true */
diff --git a/misc/node.d.ts b/misc/node.d.ts
new file mode 100644
index 0000000..18156c5
--- /dev/null
+++ b/misc/node.d.ts
@@ -0,0 +1,8 @@
+declare var require: {
+ (id: string): any;
+}
+
+declare var process: {
+ argv: string[];
+ exit(status: number): void;
+}
diff --git a/misc/xl.d.ts b/misc/xl.d.ts
new file mode 100644
index 0000000..25812bb
--- /dev/null
+++ b/misc/xl.d.ts
@@ -0,0 +1,27 @@
+interface Cell {
+ v;
+ t: string;
+ ixfe: number;
+}
+
+interface Worksheet {
+ [key: string]: Cell;
+}
+
+interface Worksheets {
+ [key: string]: Worksheet;
+}
+
+interface Workbook {
+ SheetNames: string[];
+ Sheets: Worksheets;
+}
+
+interface XLSX {
+ verbose: Number;
+ readFile(filename: string): Workbook;
+ utils: {
+ get_formulae(worksheet: Worksheet): string[];
+ make_csv(worksheet: Worksheet): string;
+ };
+}
diff --git a/misc/xlsx2csv.ts b/misc/xlsx2csv.ts
new file mode 100755
index 0000000..d1248bb
--- /dev/null
+++ b/misc/xlsx2csv.ts
@@ -0,0 +1,71 @@
+///
+///
+
+/* vim: set ts=2: */
+var XLSX = require('xlsx');
+var fs = require('fs'), program = require('commander');
+program
+ .version('0.3.1')
+ .usage('[options] [sheetname]')
+ .option('-f, --file ', 'use specified workbook')
+ .option('-s, --sheet ', 'print specified sheet (default first sheet)')
+ .option('-l, --list-sheets', 'list sheet names and exit')
+ .option('-F, --formulae', 'print formulae')
+ .option('--dev', 'development mode')
+ .option('--read', 'read but do not print out contents')
+ .option('-q, --quiet', 'quiet mode')
+ .parse(process.argv);
+
+var filename:string, sheetname:string = '';
+if(program.args[0]) {
+ filename = program.args[0];
+ if(program.args[1]) sheetname = program.args[1];
+}
+if(program.sheet) sheetname = program.sheet;
+if(program.file) filename = program.file;
+
+if(!filename) {
+ console.error("xlsx2csv: must specify a filename");
+ process.exit(1);
+}
+
+if(!fs.existsSync(filename)) {
+ console.error("xlsx2csv: " + filename + ": No such file or directory");
+ process.exit(2);
+}
+
+if(program.dev) XLSX.verbose = 2;
+
+var wb:Workbook;
+if(program.dev) wb = XLSX.readFile(filename);
+else try {
+ wb = XLSX.readFile(filename);
+} catch(e) {
+ var msg:string = (program.quiet) ? "" : "xlsx2csv: error parsing ";
+ msg += filename + ": " + e;
+ console.error(msg);
+ process.exit(3);
+}
+if(program.read) process.exit(0);
+
+if(program.listSheets) {
+ console.log(wb.SheetNames.join("\n"));
+ process.exit(0);
+}
+
+var target_sheet:string = sheetname || '';
+if(target_sheet === '') target_sheet = wb.SheetNames[0];
+
+var ws:Worksheet;
+try {
+ ws = wb.Sheets[target_sheet];
+ if(!ws) throw "Sheet " + target_sheet + " cannot be found";
+} catch(e) {
+ console.error("xlsx2csv: error parsing "+filename+" "+target_sheet+": " + e);
+ process.exit(4);
+}
+
+if(!program.quiet) console.error(target_sheet);
+if(program.formulae) console.log(XLSX.utils.get_formulae(ws).join("\n"));
+else console.log(XLSX.utils.make_csv(ws));
+console.log(ws["C2"]);
diff --git a/xlsx.js b/xlsx.js
index fe36a60..5134635 100644
--- a/xlsx.js
+++ b/xlsx.js
@@ -1,3 +1,4 @@
+/* xlsx.js (C) 2013 SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint eqnull:true */
/* Spreadsheet Format -- jump to XLSX for the XLSX code */