diff --git a/experiments/bktree/BkTree.php b/experiments/bktree/BkTree.php
index f74ffb8..b2b698a 100644
--- a/experiments/bktree/BkTree.php
+++ b/experiments/bktree/BkTree.php
@@ -104,7 +104,7 @@ class BkTree
 		// if($string == "bunny") echo("\nStart $string\n");
 		
 		$next_node = $this->box->get("node|$starting_node_id"); // Grab the root to start with
-		$next_node_id = 0;
+		$next_node_id = $starting_node_id;
 		$depth = 0; $visted = 0;
 		while(true) {
 			$visted++;
@@ -160,10 +160,11 @@ class BkTree
 			
 			$node_target_id = $node_target->children->$distance;
 			$node_target = $this->box->get("node|$node_target_id");
-			$stack[] = [ "node" => $node_target, "id" => $node_target->children->$distance ];
+			$stack[] = [ "node" => $node_target, "id" => $node_target_id ];
 		}
 		
-		$parent = end($stack); // The last item on the stack is the parent node
+		// The last item but 1 on the stack is the parent node
+		$parent = $stack[count($stack) - 2];
 		
 		// 1. Delete the connection from parent -> target
 		foreach($parent["node"]->children as $distance -> $id) {
@@ -180,16 +181,53 @@ class BkTree
 		// 2. Iterate over the target's children (if any) and re-hang them from the parent
 		// NOTE: We need to be careful that the characteristics of the tree are preserved. We should test this by tracing a node's location in the tree and purposefully removing nodes in the chain and see if the results returned as still the same
 		// 
-		// Hang the now orphaned children from the parent
+		// Hang the now orphaned children and all their decendants from the parent
 		foreach($node_target->children as $distance -> $id) {
 			$orphan = $this->box->get("node|$id");
-			// TODO: Optimise this
-			$this->box->delete("node|$id"); // Delete the orphan node
-			$this->add($orphan->value, $parent["id"]); // Re-hang it from the parent
+			$substack = [ [ "node" => $orphan, "id" => $id ] ]; $substack_top = 0;
+			while($substack_top >= 0) {
+				$next = $substack[$substack_top];
+				unset($substack[$substack_top]);
+				$substack_top--;
+				
+				$this->box->delete("node|{$next["id"]}"); // Delete the orphan node
+				$this->add($next["node"], $parent["id"]); // Re-hang it from the parent
+				
+				foreach($next["node"]->children as $distance => $sub_id) {
+					$substack[++$substack_top] = [
+						"node" => $this->box->get("node|$sub_id"),
+						"id" => $sub_id
+					];
+				}
+			}
 		}
 		
 		// Delete the target node
 		$this->box->delete("node|$node_target_id");
+		
+		return true;
+	}
+	
+	public function trace(string $string) {
+		$stack = [
+			(object) [ "node" => $this->box->get("node|0"), "id" => 0 ]
+		];
+		$node_target = $stack[0]->node;
+		
+		while($node_target->value !== $string) {
+			$distance = levenshtein($string, $node_target->value, $this->cost_insert, $this->cost_replace, $this->cost_delete);
+			
+			var_dump($node_target);
+			
+			// Failed to recurse to find the node with the value in question
+			if(!isset($node_target->children->$distance))
+				return null;
+			
+			$node_target_id = $node_target->children->$distance;
+			$node_target = $this->box->get("node|$node_target_id");
+			$stack[] = (object) [ "node" => $node_target, "id" => $node_target_id ];
+		}
+		return $stack;
 	}
 	
 	/**
@@ -259,8 +297,7 @@ class BkTree
 				// echo("[lookup] Recursing on child ".$this->box->get("node|$child->id")->value." (distance $child->distance)\n");
 				// Push the node onto the stack
 				// Note that it doesn't actually matter that the stack isn't an accurate representation of ancestor nodes at any given time here. The stack is really a hybrid between a stack and a queue, having features of both.
-				$stack_top++;
-				$stack[$stack_top] = $this->box->get("node|{$node_current->children->$child_distance}");
+				$stack[++$stack_top] = $this->box->get("node|{$node_current->children->$child_distance}");
 			}
 		}
 		
diff --git a/experiments/bktree/JsonStorageBox.php b/experiments/bktree/JsonStorageBox.php
index aac052f..23d13f2 100644
--- a/experiments/bktree/JsonStorageBox.php
+++ b/experiments/bktree/JsonStorageBox.php
@@ -134,7 +134,7 @@ class JsonStorageBox {
 	/**
 	 * Deletes an item from the data store.
 	 * @param	string	$key	The key of the item to delete.
-	 * @return	bool	Whether it was really deleted or not. Note that if it doesn't exist, then it can't be deleted.
+	 * @return	bool	Whether it was really deleted or not. Note that if it doesn't exist, then it can't be deleted. Note also that if a node is deleted before being persisted to disk, this will return false when in actuality it was deleted successfully.
 	 */
 	public function delete(string $key) : bool {
 		// Remove it from the cache
diff --git a/experiments/bktree/bktreetest.php b/experiments/bktree/bktreetest.php
index d20df51..f1c9379 100644
--- a/experiments/bktree/bktreetest.php
+++ b/experiments/bktree/bktreetest.php
@@ -73,7 +73,7 @@ else
 echo("Tree created in ".($tree["time"]*1000)."ms\n");
 $tree = $tree["value"];
 
-writegraph(); exit();
+// writegraph(); exit();
 
 function test_auto() {
 	global $tree;
@@ -98,7 +98,8 @@ while(true) {
 	readline_add_history($line);
 	
 	if($line[0] == ".") {
-		switch ($line) {
+		$parts = explode(" ", $line, 2);
+		switch ($parts[0]) {
 			case ".quit":
 			case ".exit":
 				$result = time_callable(function() use ($tree) {
@@ -110,20 +111,45 @@ while(true) {
 			
 			case ".help":
 				echo("dot commands:
-.exit          Exit, saving edits to the tree to disk
-.writegraph    Write a graphviz dot file to disk representing the tree in the current directory
-.stats         Compute statistics about the tree
+.exit               Exit, saving edits to the tree to disk
+.writegraph         Write a graphviz dot file to disk representing the tree in the current directory
+.stats              Compute statistics about the tree
+.trace {{string}}   Trace the path through the tree to {{string}}
+.remove {{string}}  Delete {{string}} from the tree
+.add {{string}}     Add {{string}} to the tree
 ");
 				break;
 			
 			case ".writegraph":
 				writegraph();
 				break;
+				
+			case ".remove":
+				$start_time = microtime(true);
+				$result = $tree->remove($parts[1]);
+				echo("{$parts[1]}".($result?"":" not")." successfully deleted from the tree in ".round((microtime(true) - $start_time)*1000)."ms\n");
+				break;
+			case ".add":
+				$start_time = microtime(true);
+				$depth = $tree->add($parts[1]);
+				echo("{$parts[1]} successfully added to the tree at depth $depth in ".round((microtime(true) - $start_time)*1000)."ms\n");
+				break;
+			
+			case ".trace":
+				$trace = $tree->trace($parts[1]);
+				foreach($trace as $depth => $item) {
+					echo("$depth: {$item->node->value} (#$item->id)\n");
+				}
+				break;
 			
 			case ".stats":
 				echo("Tree stats: ");
 				var_dump($tree->stats());
 				break;
+			
+			default:
+				echo("Error: Unknown dot-command {$parts[0]} (try .help)\n");
+				break;
 		}
 		continue;
 	}
