--- /dev/null
+# Introduction
+
+Plugins are an important aspect of Gwion's flexibility and extensibility. They allow you to customize behavior as well as develop novel functionality within Gwion itself.
+
+Much of Gwion's features _come_ from plugins. Audio generation, file I/O, image editing and more.
+
+## What is a Plugin?
+
+Plugins are shared object files typically created from C source code. They consist of a few core functions required for the Gwion runtime to properly initialize and use it.
+
+## Simple Plugin
+
+Let's create a simple plugin which provides a single function: `add`. This will take two `int`s and return their sum as an `int`.
+
+First, open up your terminal and run the following shell commands within `Gwion/plug`:
+```bash
+# Create a new directory for our Adder plugin
+mkdir Adder
+
+# Navigate to the newly created directory
+cd Adder
+
+# Create a makefile for compilation
+printf "include ../config.mk\ninclude ../config_post.mk\n" > Makefile
+
+# Create an adder.c file with your favorite text editor
+nano adder.c
+```
+
+We are greeted with any empty file. However, it won't be empty for long.
+
+Let's add the following code to the top of our file:
+```c
+#include "plugin_dev.h"
+```
+
+This will include all the necessary functions and macros to develop a plugin without much head scratching.
+
+Next, we need the `GWION_IMPORT` function. This is extremely important since it is what the Gwion runtime uses to set up your plugin. `GWION_IMPORT` is a macro which takes the name of your plugin: in this case that is "Adder". Underneath the `include` let's add:
+```c
+GWION_IMPORT(Adder) {
+ // Init code here
+}
+```
+
+Within this function we register the public API of our plugin to Gwion. In our case, we want an `Adder` class with a single static function `add` that takes two numbers and returns their sum.
+
+Our first step is to create the `Adder` class. This is done with:
+```c
+GWION_IMPORT(Adder) {
+ // Begin our adder class
+ DECL_OB(const Type, t_adder, = gwi_class_ini(gwi, "Adder", "Object"));
+}
+```
+
+Now, whenever we `ini` a class, we must also `end` it:
+
+```c
+GWION_IMPORT(Adder) {
+ // Begin our adder class
+ DECL_OB(const Type, t_adder, = gwi_class_ini(gwi, "Adder", "Object"));
+
+ // End our adder class
+ GWI_BB(gwi_class_end(gwi));
+}
+```
+
+We also want to make sure to indicate that everything has gone OK. We do this by returning `GW_OK`:
+```c
+GWION_IMPORT(Adder) {
+ // Begin our adder class
+ DECL_OB(const Type, t_adder, = gwi_class_ini(gwi, "Adder", "Object"));
+
+ // End our adder class
+ GWI_BB(gwi_class_end(gwi));
+
+ return GW_OK;
+}
+```
+
+Right now our code doesn't really do much; it creates an empty class and then exits. Let's expand this code to add a static function inside the class:
+```c
+GWION_IMPORT(Adder) {
+ // Begin our adder class
+ DECL_OB(const Type, t_adder, = gwi_class_ini(gwi, "Adder", "Object"));
+
+ // Create a new function named `add` with a return type of `int`
+ // gwi_func_ini(gwi, return_type, name);
+ GWI_BB(gwi_func_ini(gwi, "int", "add"));
+
+ // Register our two args `a` and `b` of type `int`
+ // gwi_func_arg(gwi, arg_type, name);
+ GWI_BB(gwi_func_arg(gwi, "int", "a"));
+ GWI_BB(gwi_func_arg(gwi, "int", "b"));
+
+ // Mark the function as completely declared
+ GWI_BB(gwi_func_end(gwi, adder_add, ae_flag_static));
+
+ // End our adder class
+ GWI_BB(gwi_class_end(gwi));
+
+ return GW_OK;
+}
+```
+
+Looks like we are good to go! Let's compile...and:
+```
+adder.c: In function 'import':
+adder.c:22:28: error: 'adder_add' undeclared (first use in this function)
+ 22 | GWI_BB(gwi_func_end(gwi, adder_add, ae_flag_static))
+ | ^~~~~~~~~
+```
+
+When we marked the function as completely declared with `gwi_func_end`, we gave the function implementation `adder_add` as an argument. This tells Gwion that our `Adder.add` function in Gwion corresponds to the C function `adder_add`. However we haven't actually defined it! Let's do that. Above our `GWION_IMPORT` function, add:
+
+```c
+// The `SFUN` macro defines a static function
+// The `static` here is actually a C keyword, unrelated to Gwion
+static SFUN(sfun) {
+ // Function body
+}
+```
+
+Let's recall what our `Adder.add` function does. It takes two `int` parameters and returns an `int`. Gwion provides facilities for doing this:
+
+```c
+// The `SFUN` macro defines a static function
+// The `static` here is actually a C keyword, unrelated to Gwion
+static SFUN(sfun) {
+ // Retrieve the arguments
+ // `a` is in memory at offset 0
+ const m_int a = *(m_int*)MEM(0);
+ // `b` is in memory at offset `SZ_INT`
+ // This is because `a` has size `SZ_INT` and `b` is after `a`
+ const m_int b = *(m_int*)MEM(SZ_INT);
+
+ // We now set the return value, given as a void pointer with the `RETURN` macro
+ // We need to cast it to the pointer type we want to return and then assign the return value
+ *(m_int*)RETURN = a + b;
+}
+```
+
+Finally, we can test our plugin. After running `make` (which creates `Adder.so`) in the directory, create a new file called `add.gw` and insert the following code:
+```gwion
+#! We import our newly created plugin
+#require Adder
+
+#! Let's call our add function
+<<< Adder.add(1, 2) >>>;
+```
+
+If all goes well, running the following shell command should result in "3" being printed:
+```bash
+gwion -p. add.gw
+```