diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..052641ebf545316f793af5a5a39bffaf4cb0ef3d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+# Utility Macros
+
+## Usage
+
+### Add to your project
+
+```toml
+[dependencies]
+# There is not presently a crates.io release
+weirdboi_utils = { git = "https://weirdboi.dev/libraries/weirdboi-utils.git", rev = "put-a-revision-here" }
+```
+
+### Build Collections
+
+Build hashmaps in-place with the `hashmap` macro
+
+```rust
+let some_output = function_call("string", 23, hashmap! {
+    "key" => 123,
+    "another_key" => 456
+});
+```
+
+### Safe Unwrapping
+
+When you want to simply do nothing and cease further execution without a panic, the convenience `some!` and `ok!` macros are handy:
+
+```rust
+fn do_something_without_fail(value: Result<A, B>, maybe: Option<F>) {
+    let value = ok!(value);
+    let maybe = some!(maybe);
+
+    println!("Value was OK and maybe was SOME");
+}
+```
+
+Alternatively, in a loop you can skip the rest of the current iteration instead of ending executino entirely:
+
+```rust
+fn do_many_things(list: impl Iter<Item = Option<F>>) {
+    for item in list {
+        let current = some!(item; continue);
+        println!("Found SOME: {}", current);
+    }
+}
+```
+
+Finally, if the function has a return type then you should specify a default value to return:
+
+```rust
+fn get_widget(maybe: Result<A, B>) -> i32 {
+    let maybe = ok!(maybe; -1); // Returns "-1" from the function if maybe is Err(_)
+}
+```
\ No newline at end of file