diff --git a/.gitignore b/.gitignore
index ba354c63..eab159d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
 *.o
 *~
+.*.sw[a-p]
+tags
 
 jq
 jq.1
diff --git a/builtin.c b/builtin.c
index 071cb564..e6cfa4da 100644
--- a/builtin.c
+++ b/builtin.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <string.h>
 #include "builtin.h"
 #include "compile.h"
@@ -5,6 +6,7 @@
 #include "locfile.h"
 #include "jv_aux.h"
 #include "jv_unicode.h"
+#include "main.h"
 
 
 
@@ -566,16 +568,44 @@ static const char* const jq_builtins[] = {
 };
 
 
-block builtins_bind(block b) {
-  for (int i=(int)(sizeof(jq_builtins)/sizeof(jq_builtins[0]))-1; i>=0; i--) {
-    struct locfile src;
-    locfile_init(&src, jq_builtins[i], strlen(jq_builtins[i]));
-    block funcs;
-    int nerrors = jq_parse_library(&src, &funcs);
-    assert(!nerrors);
-    b = block_bind_referenced(funcs, b, OP_IS_CALL_PSEUDO);
-    locfile_free(&src);
+int builtins_bind_one(block* bb, const char* code) {
+  struct locfile src;
+  locfile_init(&src, code, strlen(code));
+  block funcs;
+  int nerrors = jq_parse_library(&src, &funcs);
+  if (nerrors == 0) {
+    *bb = block_bind_referenced(funcs, *bb, OP_IS_CALL_PSEUDO);
   }
-  b = bind_bytecoded_builtins(b);
-  return gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), b);
+  locfile_free(&src);
+  return nerrors;
+}
+
+int slurp_lib(block* bb) {
+  int nerrors = 0;
+  char* home = getenv("HOME");
+  if (home) {    // silently ignore no $HOME
+    jv filename = jv_string_append_str(jv_string(home), "/.jq");
+    jv data = slurp_file(jv_string_value(filename), 1);
+    if (jv_is_valid(data)) {
+      nerrors = builtins_bind_one(bb, jv_string_value(data) );
+    }
+    jv_free(filename);
+    jv_free(data);
+  }
+  return nerrors;
+}
+
+int builtins_bind(block* bb) {
+  int nerrors = slurp_lib(bb);
+  if (nerrors) {
+    block_free(*bb);
+    return nerrors;
+  }
+  for (int i=(int)(sizeof(jq_builtins)/sizeof(jq_builtins[0]))-1; i>=0; i--) {
+    nerrors = builtins_bind_one(bb, jq_builtins[i]);
+    assert(!nerrors);
+  }
+  *bb = bind_bytecoded_builtins(*bb);
+  *bb = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), *bb);
+  return nerrors;
 }
diff --git a/builtin.h b/builtin.h
index 538a1391..fdbce92a 100644
--- a/builtin.h
+++ b/builtin.h
@@ -3,7 +3,7 @@
 
 #include "compile.h"
 
-block builtins_bind(block);
+int builtins_bind(block*);
 
 
 typedef void (*cfunction_ptr)(void);
diff --git a/execute.c b/execute.c
index fe8e6985..44cf2ba9 100644
--- a/execute.c
+++ b/execute.c
@@ -611,8 +611,10 @@ struct bytecode* jq_compile_args(const char* str, jv args) {
       jv_free(name);
     }
     jv_free(args);
-    program = builtins_bind(program);
-    nerrors = block_compile(program, &locations, &bc);
+    nerrors = builtins_bind(&program);
+    if (nerrors == 0) {
+      nerrors = block_compile(program, &locations, &bc);
+    }
   }
   if (nerrors) {
     fprintf(stderr, "%d compile %s\n", nerrors, nerrors > 1 ? "errors" : "error");
diff --git a/main.c b/main.c
index 1e951849..72ffbc1c 100644
--- a/main.c
+++ b/main.c
@@ -93,7 +93,7 @@ static void process(jv value, int flags) {
   jq_teardown(&jq);
 }
 
-static jv slurp_file(const char* filename, int raw) {
+jv slurp_file(const char* filename, int raw) {
   FILE* file = fopen(filename, "r");
   struct jv_parser parser;
   jv data;
diff --git a/main.h b/main.h
new file mode 100644
index 00000000..ec600395
--- /dev/null
+++ b/main.h
@@ -0,0 +1,9 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "compile.h"
+
+jv slurp_file(const char*, int);
+
+
+#endif