diff --git a/src/anybase.rs b/src/anybase.rs
index cb92caa..9fcd968 100644
--- a/src/anybase.rs
+++ b/src/anybase.rs
@@ -70,13 +70,41 @@ pub fn encode(text: String, base: u32, char_length: u32) -> String {
     return results;
 }
 
+/// Decodes catspeak into text using any base up to [`max_base()`]
+///
+/// `char_length` is set manually, but the minimum can be generated using [`char_length()`]
+///
+/// ```
+/// use cat2text::anybase;
+/// let text = "meow mewo; mrrp mreow mrrp nyaaaa~ mreow mreow meow nyaaaa~; meow mrow meow mrrp mreow meow mrrp mewo".to_string();
+/// let base = 10;
+/// let char_length = anybase::char_length(base);
 
-#[test]
-fn test_anybase_encode() {
-    use crate::anybase;
-    let text = "i love cats".to_string();
-    let base = 10;
-    let char_length = anybase::char_length(base);
-
-    assert_eq!("", anybase::encode(text, base, char_length));
+/// assert_eq!("i love cats", anybase::decode(text, base, char_length));
+/// ```
+pub fn decode(text: String, base: u32, char_length: u32) -> String {
+    let catspeak_words: Vec<String> = text.split("; ").map(|item| item.to_string()).collect();
+    let mut output: String = String::new();
+    let mut shortened_alphabet = alphabet();
+    shortened_alphabet.truncate(base as usize);
+    for engl_word in catspeak_words {
+        let mut word = String::new();
+        for engl_letter in core::split_every_x(engl_word, char_length as usize) {
+            let char_num = core::cat_to_num(
+                engl_letter
+                    .split(" ")
+                    .map(|item| item.to_string())
+                    .collect(),
+                shortened_alphabet.clone(),
+                char_length,
+            );
+            word += String::from_utf8(vec![(char_num + 96) as u8])
+                .unwrap()
+                .as_str();
+        }
+        word += " ";
+        output += word.as_str();
+    }
+    return output.trim().to_string();
 }
+
diff --git a/src/core.rs b/src/core.rs
index d5c0dba..1b75195 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -13,7 +13,6 @@ pub fn num_to_cat(num: u32, alphabet: Vec<String>, char_length: u32) -> String {
     let base: u32 = alphabet.len() as u32;
 
     // base*n*-ifying logic
-    // FIXME: With base 10 this loops 100 times? see `anybase::test_anybase_encode()`
     let mut nums: Vec<u32> = Vec::new();
     while (nums.len() as u32) < char_length {
         nums.push((num as u32) % base);
diff --git a/src/lib.rs b/src/lib.rs
index d5ac1ee..a5e9911 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,5 @@
 #![doc = include_str!("../README.md")]
-//pub mod anybase;
+pub mod anybase;
 pub mod base4;
 pub mod core;
 pub mod bytes;