diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go
index 56085442619ac19c5f39fa78db5a4ce319f31937..1d0c122cd213028b1459d8224a579521009b5804 100644
--- a/cmd/ipfs/init.go
+++ b/cmd/ipfs/init.go
@@ -5,6 +5,8 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"os"
+	"path"
 
 	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
 	assets "github.com/ipfs/go-ipfs/assets"
@@ -36,7 +38,10 @@ var initCmd = &cmds.Command{
 		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
 	},
 	PreRun: func(req cmds.Request) error {
-		daemonLocked := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
+		daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
+		if err != nil {
+			return err
+		}
 
 		log.Info("checking if daemon is running...")
 		if daemonLocked {
@@ -47,6 +52,10 @@ var initCmd = &cmds.Command{
 		return nil
 	},
 	Run: func(req cmds.Request, res cmds.Response) {
+		if req.Context().Online {
+			res.SetError(errors.New("init must be run offline only!"), cmds.ErrNormal)
+			return
+		}
 
 		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
 		if err != nil {
@@ -64,15 +73,10 @@ var initCmd = &cmds.Command{
 			nBitsForKeypair = nBitsForKeypairDefault
 		}
 
-		rpipe, wpipe := io.Pipe()
-		go func() {
-			defer wpipe.Close()
-			if err := doInit(wpipe, req.Context().ConfigRoot, force, nBitsForKeypair); err != nil {
-				res.SetError(err, cmds.ErrNormal)
-				return
-			}
-		}()
-		res.SetOutput(rpipe)
+		if err := doInit(os.Stdout, req.Context().ConfigRoot, force, nBitsForKeypair); err != nil {
+			res.SetError(err, cmds.ErrNormal)
+			return
+		}
 	},
 }
 
@@ -82,8 +86,7 @@ Reinitializing would overwrite your keys.
 `)
 
 func initWithDefaults(out io.Writer, repoRoot string) error {
-	err := doInit(out, repoRoot, false, nBitsForKeypairDefault)
-	return err
+	return doInit(out, repoRoot, false, nBitsForKeypairDefault)
 }
 
 func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) error {
@@ -91,6 +94,10 @@ func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) err
 		return err
 	}
 
+	if err := checkWriteable(repoRoot); err != nil {
+		return err
+	}
+
 	if fsrepo.IsInitialized(repoRoot) && !force {
 		return errRepoExists
 	}
@@ -117,6 +124,34 @@ func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) err
 	return initializeIpnsKeyspace(repoRoot)
 }
 
+func checkWriteable(dir string) error {
+	_, err := os.Stat(dir)
+	if err == nil {
+		// dir exists, make sure we can write to it
+		testfile := path.Join(dir, "test")
+		fi, err := os.Create(testfile)
+		if err != nil {
+			if os.IsPermission(err) {
+				return fmt.Errorf("%s is not writeable by the current user", dir)
+			}
+			return fmt.Errorf("unexpected error while checking writeablility of repo root: %s", err)
+		}
+		fi.Close()
+		return os.Remove(testfile)
+	}
+
+	if os.IsNotExist(err) {
+		// dir doesnt exist, check that we can create it
+		return os.Mkdir(dir, 0775)
+	}
+
+	if os.IsPermission(err) {
+		return fmt.Errorf("cannot write to %s, incorrect permissions", err)
+	}
+
+	return err
+}
+
 func addDefaultAssets(out io.Writer, repoRoot string) error {
 	ctx, cancel := context.WithCancel(context.Background())
 	defer cancel()
diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go
index e34492ca89bb5f145488ebc7eea03c330fa8826d..24b4443474d77f08cbaf3fc31030ab45ea4116cb 100644
--- a/cmd/ipfs/main.go
+++ b/cmd/ipfs/main.go
@@ -387,7 +387,10 @@ func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.C
 
 	// at this point need to know whether daemon is running. we defer
 	// to this point so that some commands dont open files unnecessarily.
-	daemonLocked := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
+	daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
+	if err != nil {
+		return false, err
+	}
 
 	if daemonLocked {
 
diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go
index ce64fce2735dfa5e6db9d2f3783ad80eca697d2c..446458a374062285dd65ba236ab0bf84934a0596 100644
--- a/repo/fsrepo/fsrepo.go
+++ b/repo/fsrepo/fsrepo.go
@@ -283,7 +283,7 @@ func Remove(repoPath string) error {
 
 // LockedByOtherProcess returns true if the FSRepo is locked by another
 // process. If true, then the repo cannot be opened by this process.
-func LockedByOtherProcess(repoPath string) bool {
+func LockedByOtherProcess(repoPath string) (bool, error) {
 	repoPath = path.Clean(repoPath)
 
 	// TODO replace this with the "api" file
diff --git a/repo/fsrepo/lock/lock.go b/repo/fsrepo/lock/lock.go
index f4fcd80b729cd90815bd294f0e9795542f297ef9..98387aceb6d9c98fa316e81849a3d59e99170d2b 100644
--- a/repo/fsrepo/lock/lock.go
+++ b/repo/fsrepo/lock/lock.go
@@ -2,6 +2,7 @@ package lock
 
 import (
 	"io"
+	"os"
 	"path"
 
 	lock "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/camlistore/lock"
@@ -17,14 +18,17 @@ func Lock(confdir string) (io.Closer, error) {
 	return c, err
 }
 
-func Locked(confdir string) bool {
+func Locked(confdir string) (bool, error) {
 	if !util.FileExists(path.Join(confdir, LockFile)) {
-		return false
+		return false, nil
 	}
 	if lk, err := Lock(confdir); err != nil {
-		return true
+		if os.IsPermission(err) {
+			return false, err
+		}
+		return true, nil
 	} else {
 		lk.Close()
-		return false
+		return false, nil
 	}
 }
diff --git a/test/sharness/t0020-init.sh b/test/sharness/t0020-init.sh
index 5ee134a36d556f793effb1cb02e37e84182d6590..306dbf6adb192cf8c024752dc5bc1409db93b620 100755
--- a/test/sharness/t0020-init.sh
+++ b/test/sharness/t0020-init.sh
@@ -8,6 +8,22 @@ test_description="Test init command"
 
 . lib/test-lib.sh
 
+# test that ipfs fails to init if IPFS_PATH isnt writeable
+test_expect_success "create dir and change perms succeeds" '
+	export IPFS_PATH="$(pwd)/.badipfs" &&
+	mkdir "$IPFS_PATH" &&
+	chmod 000 "$IPFS_PATH"
+'
+
+test_expect_success "ipfs init fails" '
+	test_must_fail ipfs init 2> init_fail_out
+'
+
+test_expect_success "ipfs init output looks good" '
+	echo "Error: open $IPFS_PATH/repo.lock: permission denied" > init_fail_exp &&
+	test_cmp init_fail_out init_fail_exp
+'
+
 test_expect_success "ipfs init succeeds" '
 	export IPFS_PATH="$(pwd)/.ipfs" &&
 	BITS="2048" &&
@@ -17,7 +33,8 @@ test_expect_success "ipfs init succeeds" '
 test_expect_success ".ipfs/ has been created" '
 	test -d ".ipfs" &&
 	test -f ".ipfs/config" &&
-	test -d ".ipfs/datastore" ||
+	test -d ".ipfs/datastore" &&
+	test -d ".ipfs/blocks" ||
 	test_fsh ls -al .ipfs
 '
 
@@ -44,6 +61,10 @@ test_expect_success "ipfs init output looks good" '
 	test_cmp expected actual_init
 '
 
+test_expect_success "clean up ipfs dir" '
+	rm -rf "$IPFS_PATH"
+'
+
 test_init_ipfs
 
 test_launch_ipfs_daemon