diff --git a/README.md b/README.md
index f035f06..1330b0d 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,9 @@ Missing documentation.
 Missing documentation.
 
 ### Settings
+- `thickness`, default 30
+- `color`, default black
+- `cap`, default square
 
 ### Methods
 - `stroke:`, no details.
@@ -82,11 +85,12 @@ Missing documentation.
 Cursor magnetisation settings.
 
 ### Settings
-- `size`, default 15
-- `rate`, default 4
+- `size`, default 0
+- `step`, default 4
 
 ### Methods
 - `lock:`, no details.
+- `unlock:`, no details.
 
 ### Ports
 
diff --git a/sources/index.html b/sources/index.html
index d8817f7..cfd93c1 100644
--- a/sources/index.html
+++ b/sources/index.html
@@ -3,7 +3,6 @@
     <script type="text/javascript" src="scripts/core/module.js"></script>
     <script type="text/javascript" src="scripts/modules/frame.js"></script>
     <script type="text/javascript" src="scripts/modules/brush.js"></script>
-    <script type="text/javascript" src="scripts/modules/eraser.js"></script>
     <script type="text/javascript" src="scripts/modules/line.js"></script>
     <script type="text/javascript" src="scripts/modules/io.js"></script>
     <script type="text/javascript" src="scripts/modules/path.js"></script>
diff --git a/sources/scripts/core/cursor.js b/sources/scripts/core/cursor.js
index 3108ec7..5d0703b 100644
--- a/sources/scripts/core/cursor.js
+++ b/sources/scripts/core/cursor.js
@@ -61,7 +61,10 @@ function Cursor(rune)
 
     }
     else if(e.altKey){
-      ronin.eraser.stroke(ronin.cursor.line);
+      ronin.brush.erase(ronin.cursor.line);
+    }
+    else if(e.shiftKey){
+      ronin.cursor.drag(ronin.cursor.line);
     }
     else{
       ronin.brush.stroke(ronin.cursor.line);  
@@ -91,6 +94,20 @@ function Cursor(rune)
     ronin.cursor.query = ronin.commander.input_el.value;
   }
 
+  this.drag = function(line)
+  {
+    var offset = make_offset(line.from,line.to);
+    var data = ronin.render.select();
+    ronin.render.clear();
+    ronin.render.context().putImageData(data, offset.x * -2, offset.y * -2);
+  }
+
+  function make_offset(a,b)
+  {
+    return {x:a.x-b.x,y:a.y-b.y};
+  }
+
+
   this.inject_query = function()
   {
     if(ronin.cursor.query && ronin.cursor.query.indexOf("$") < 0){ return; }
diff --git a/sources/scripts/core/layer.js b/sources/scripts/core/layer.js
index c1be32d..c467934 100644
--- a/sources/scripts/core/layer.js
+++ b/sources/scripts/core/layer.js
@@ -28,12 +28,12 @@ function Layer()
     this.el.style.height = size.height+"px";
   }
 
-  this.select = function(x,y,width,height)
+  this.select = function(x = 0,y = 0,width = ronin.frame.settings.width,height = ronin.frame.settings.width)
   {
     return this.context().getImageData(x, y, width * 2, height * 2);
   }
 
-  this.to_data = function()
+  this.to_base64 = function()
   {
     return this.el.toDataURL('image/png');
   }
@@ -41,7 +41,7 @@ function Layer()
   this.to_img = function()
   {
     var img = new Image();
-    img.src = this.to_data();
+    img.src = this.to_base64();
     return img;
   }
 
diff --git a/sources/scripts/layers/grid.js b/sources/scripts/layers/grid.js
index ac7012a..a28b5aa 100644
--- a/sources/scripts/layers/grid.js
+++ b/sources/scripts/layers/grid.js
@@ -6,6 +6,8 @@ function Grid()
 
   this.draw = function(size = 60, step = 5)
   {
+    this.clear();
+    
     var x = 1;
     var size = size * 2;
     while(x < this.el.width/size){
diff --git a/sources/scripts/modules/brush.js b/sources/scripts/modules/brush.js
index db55205..05e4f48 100644
--- a/sources/scripts/modules/brush.js
+++ b/sources/scripts/modules/brush.js
@@ -83,6 +83,20 @@ function Brush()
     }
   }
 
+  this.erase = function(line)
+  {
+    var ctx = ronin.render.context();
+
+    ctx.beginPath();
+    ctx.globalCompositeOperation="destination-out";
+    ctx.moveTo(line.from.x * 2,line.from.y * 2);
+    ctx.lineTo(line.to.x * 2,line.to.y * 2);
+    ctx.lineCap="round";
+    ctx.lineWidth = this.thickness(line);
+    ctx.stroke();
+    ctx.closePath();
+  }
+
   this.mod_size = function(mod)
   {
     this.settings.size = clamp(this.settings.size+mod,1,100);
diff --git a/sources/scripts/modules/eraser.js b/sources/scripts/modules/eraser.js
deleted file mode 100644
index d78e176..0000000
--- a/sources/scripts/modules/eraser.js
+++ /dev/null
@@ -1,23 +0,0 @@
-function Eraser()
-{
-  Module.call(this,"eraser");
-
-  this.thickness = function(line)
-  {
-    return ronin.brush.thickness(line);
-  }
-
-  this.stroke = function(line)
-  {
-    var ctx = ronin.render.context();
-
-    ctx.beginPath();
-    ctx.globalCompositeOperation="destination-out";
-    ctx.moveTo(line.from.x * 2,line.from.y * 2);
-    ctx.lineTo(line.to.x * 2,line.to.y * 2);
-    ctx.lineCap="round";
-    ctx.lineWidth = this.thickness(line);
-    ctx.stroke();
-    ctx.closePath();
-  }
-}
\ No newline at end of file
diff --git a/sources/scripts/modules/io.js b/sources/scripts/modules/io.js
index b5e366b..f923ac5 100644
--- a/sources/scripts/modules/io.js
+++ b/sources/scripts/modules/io.js
@@ -37,7 +37,7 @@ function IO()
   this.render = function()
   {
     var fs = require('fs');
-    var data = ronin.render.to_data().replace(/^data:image\/\w+;base64,/, "");
+    var data = ronin.render.to_base64().replace(/^data:image\/\w+;base64,/, "");
     var buf = new Buffer(data, 'base64');
 
     dialog.showSaveDialog((fileName) => {
diff --git a/sources/scripts/modules/magnet.js b/sources/scripts/modules/magnet.js
index 946c828..bf93a49 100644
--- a/sources/scripts/modules/magnet.js
+++ b/sources/scripts/modules/magnet.js
@@ -2,26 +2,29 @@ function Magnet()
 {
   Module.call(this,"magnet","Cursor magnetisation settings.");
 
-  this.settings = {size:15,rate:4};
+  this.settings = {size:0,step:4};
 
   this.methods.lock = function(q)
   {
     var size = parseInt(q);
 
-    if(size < 5){ return; }
+    if(size < 5){ this.unlock(); return; }
 
-    console.log(size)
-
-    ronin.grid.draw(size);
+    ronin.grid.draw(size,ronin.magnet.settings.step);
   }
 
   this.methods.unlock = function(q)
   {
-    console.log(q)    
+    ronin.magnet.settings.size = 0;
+    ronin.grid.clear();
   }
 
   this.filter = function(pos)
   {
+    if(this.settings.size < 5){
+      return pos;
+    }
+
     var s = this.settings.size;
     return {x:parseInt(pos.x/s)*s,y:parseInt(pos.y/s)*s};
   }
diff --git a/sources/scripts/modules/path.js b/sources/scripts/modules/path.js
index 0e2c0ce..b88916e 100644
--- a/sources/scripts/modules/path.js
+++ b/sources/scripts/modules/path.js
@@ -2,6 +2,8 @@ function Path()
 {
   Module.call(this,"path");
 
+  this.settings = {thickness:30,color:"black",cap:"square"};
+
   this.methods.stroke = function(q)
   {
     ronin.preview.clear();
@@ -32,9 +34,9 @@ function Path()
 
     var ctx = ronin.preview.context();
     ctx.beginPath();
-    ctx.lineCap = "butt";
-    ctx.lineWidth = 30;
-    ctx.strokeStyle = "black";
+    ctx.lineCap = q.settings.cap ? q.settings.cap : ronin.path.settings.cap;
+    ctx.lineWidth = q.settings.thickness ? q.settings.thickness : ronin.path.settings.thickness;
+    ctx.strokeStyle = q.settings.color ? q.settings.color : ronin.path.settings.color;
     ctx.stroke(new Path2D(path));
     ctx.closePath();
   }
diff --git a/sources/scripts/ronin.js b/sources/scripts/ronin.js
index ec86c53..01c130b 100644
--- a/sources/scripts/ronin.js
+++ b/sources/scripts/ronin.js
@@ -16,7 +16,6 @@ function Ronin()
 
   this.io = new IO();
   this.brush = new Brush();
-  this.eraser = new Eraser();
   this.frame = new Frame();
   this.line = new Line();
   this.path = new Path();
@@ -77,6 +76,6 @@ function Ronin()
 
     // this.commander.input_el.value = "io import:~/Desktop/test.png anchor=$";
     // this.commander.input_el.value = "path stroke:$+";
-    this.commander.input_el.value = "magnet lock:";
+    // this.commander.input_el.value = "magnet lock:";
   }
 }
\ No newline at end of file