diff --git a/py/emitcpy.c b/py/emitcpy.c
index 52f804925c8a49604915234cd5bb439644df18c7..b107c0bf1151305d18cdd6f733d4647eb25a0fd3 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -131,7 +131,7 @@ static void emit_cpy_import_star(emit_t *emit) {
     }
 }
 
-static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
+static void emit_cpy_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
     emit_pre(emit, 1, 3);
     if (emit->pass == PASS_3) {
         printf("LOAD_CONST ");
diff --git a/unix/lexerunix.c b/py/lexerunix.c
similarity index 100%
rename from unix/lexerunix.c
rename to py/lexerunix.c
diff --git a/unix/lexerunix.h b/py/lexerunix.h
similarity index 100%
rename from unix/lexerunix.h
rename to py/lexerunix.h
diff --git a/unix-cpy/.gitignore b/unix-cpy/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e3778ee72138ecc4ca25124009008455cd85467d
--- /dev/null
+++ b/unix-cpy/.gitignore
@@ -0,0 +1,2 @@
+build
+cpy
diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..475b6bd9d483b30f96ef5996333ea7cdb438b401
--- /dev/null
+++ b/unix-cpy/Makefile
@@ -0,0 +1,90 @@
+PYSRC=../py
+BUILD=build
+
+CC = gcc
+CFLAGS = -I. -I$(PYSRC) -Wall -Werror -ansi -std=gnu99 -Os #-DNDEBUG
+LDFLAGS = -lm
+
+SRC_C = \
+	main.c \
+
+PY_O = \
+	nlrx64.o \
+	malloc.o \
+	qstr.o \
+	vstr.o \
+	misc.o \
+	lexer.o \
+	lexerunix.o \
+	parse.o \
+	scope.o \
+	compile.o \
+	emitcommon.o \
+	emitpass1.o \
+	emitcpy.o \
+	runtime.o \
+	map.o \
+	obj.o \
+	objbool.o \
+	objboundmeth.o \
+	objcell.o \
+	objclass.o \
+	objclosure.o \
+	objcomplex.o \
+	objdict.o \
+	objexcept.o \
+	objfloat.o \
+	objfun.o \
+	objgenerator.o \
+	objinstance.o \
+	objlist.o \
+	objnone.o \
+	objrange.o \
+	objset.o \
+	objstr.o \
+	objtuple.o \
+	objtype.o \
+	builtin.o \
+	vm.o \
+	showbc.o \
+	repl.o \
+
+OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(PY_O))
+LIB =
+PROG = cpy
+
+$(PROG): $(BUILD) $(OBJ)
+	$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
+
+$(BUILD):
+	mkdir $@
+
+$(BUILD)/%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+$(BUILD)/%.o: $(PYSRC)/%.s
+	$(AS) -o $@ $<
+
+$(BUILD)/%.o: $(PYSRC)/%.c mpconfig.h
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+$(BUILD)/emitnx64.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
+	$(CC) $(CFLAGS) -DN_X64 -c -o $@ $<
+
+$(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
+	$(CC) $(CFLAGS) -DN_THUMB -c -o $@ $<
+
+# optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster)
+$(BUILD)/vm.o: $(PYSRC)/vm.c
+	$(CC) $(CFLAGS) -O3 -c -o $@ $<
+
+$(BUILD)/main.o: mpconfig.h
+$(BUILD)/parse.o: $(PYSRC)/grammar.h
+$(BUILD)/compile.o: $(PYSRC)/grammar.h
+$(BUILD)/emitcpy.o: $(PYSRC)/emit.h
+$(BUILD)/emitbc.o: $(PYSRC)/emit.h
+
+clean:
+	/bin/rm -r $(BUILD)
+
+.PHONY: clean
diff --git a/unix-cpy/main.c b/unix-cpy/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b59df4f374e09966a55cfbb78c3a79f166aff7a
--- /dev/null
+++ b/unix-cpy/main.c
@@ -0,0 +1,69 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "lexer.h"
+#include "lexerunix.h"
+#include "parse.h"
+#include "compile.h"
+#include "obj.h"
+#include "runtime0.h"
+#include "runtime.h"
+
+void do_file(const char *file) {
+    mp_lexer_t *lex = mp_lexer_new_from_file(file);
+    if (lex == NULL) {
+        return;
+    }
+
+    if (0) {
+        // just tokenise
+        while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
+            mp_token_show(mp_lexer_cur(lex));
+            mp_lexer_to_next(lex);
+        }
+        mp_lexer_free(lex);
+
+    } else {
+        // compile
+
+        mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
+        mp_lexer_free(lex);
+
+        if (pn != MP_PARSE_NODE_NULL) {
+            //printf("----------------\n");
+            //parse_node_show(pn, 0);
+            //printf("----------------\n");
+            bool comp_ok = mp_compile(pn, false);
+            //printf("----------------\n");
+
+            if (!comp_ok) {
+                printf("compile error\n");
+            }
+        }
+    }
+}
+
+int main(int argc, char **argv) {
+    qstr_init();
+    rt_init();
+
+    if (argc == 2) {
+        do_file(argv[1]);
+    } else {
+        printf("usage: py [<file>]\n");
+        return 1;
+    }
+    rt_deinit();
+
+    return 0;
+}
+
+// for sqrt
+#include <math.h>
+machine_float_t machine_sqrt(machine_float_t x) {
+    return sqrt(x);
+}
diff --git a/unix-cpy/mpconfig.h b/unix-cpy/mpconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fe8a7ac2eebffa1d1d5a14896ecd9ebd12d8f5b
--- /dev/null
+++ b/unix-cpy/mpconfig.h
@@ -0,0 +1,19 @@
+// options to control how Micro Python is built
+
+#define MICROPY_ENABLE_FLOAT        (1)
+#define MICROPY_EMIT_CPYTHON        (1)
+#define MICROPY_EMIT_X64            (0)
+#define MICROPY_EMIT_THUMB          (0)
+#define MICROPY_EMIT_INLINE_THUMB   (0)
+
+// type definitions for the specific machine
+
+#define BYTES_PER_WORD (8)
+
+typedef int64_t machine_int_t; // must be pointer size
+typedef uint64_t machine_uint_t; // must be pointer size
+typedef void *machine_ptr_t; // must be of pointer size
+typedef const void *machine_const_ptr_t; // must be of pointer size
+typedef double machine_float_t;
+
+machine_float_t machine_sqrt(machine_float_t x);
diff --git a/unix/.gitignore b/unix/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a90e4976e694dbf88ceb3c4bf4ace4928f6e42d0
--- /dev/null
+++ b/unix/.gitignore
@@ -0,0 +1,3 @@
+build
+py
+*.py
diff --git a/unix/Makefile b/unix/Makefile
index 463f6b170bc6f5d8153b370d67b4fab258c882de..441804e50951205f511a7118b145f6eb9fa837e8 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -7,7 +7,6 @@ LDFLAGS = -lm
 
 SRC_C = \
 	main.c \
-	lexerunix.c \
 
 PY_O = \
 	nlrx64.o \
@@ -16,6 +15,7 @@ PY_O = \
 	vstr.o \
 	misc.o \
 	lexer.o \
+	lexerunix.o \
 	parse.o \
 	scope.o \
 	compile.o \
@@ -94,3 +94,5 @@ $(BUILD)/emitbc.o: $(PYSRC)/emit.h
 
 clean:
 	/bin/rm -r $(BUILD)
+
+.PHONY: clean