diff --git a/.gitignore b/.gitignore
index 61ead86..8b7ef35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/vendor
+composer.lock
diff --git a/PRESETS.md b/PRESETS.md
new file mode 100644
index 0000000..162fee4
--- /dev/null
+++ b/PRESETS.md
@@ -0,0 +1,114 @@
+VfxApply Presets Documentation
+==============================
+
+
+## Preset keys
+
+**Common keys**
+
+| Key | Type | Description
+|------.------------|----------------|-------------------------------------------
+| `preset/name` | *String* | A description string for this preset
+| `preset/group` | *String|Null* | Logical grouping
+| `preset/plugin` | *String* | The id of the plugin this preset is for
+| `preset/props` | *Array* | Properties used by the plugin
+| `preset/params` | *Array|Null* | Parameters for tweaking
+
+## Properties
+
+**ffmpeg**
+
+| Property | Type | Description
+|-------------------|----------------|-------------------------------------------
+| `filter` | *String* | The filter string, with optional param placeholders
+| `extra` | *String|Null* | Extra options to pass on the ffmpeg command line
+| `type` | *Enum|Null* | ffmpeg filter type; One of `complex` (default), `audio` or `video`
+
+
+**natron**
+
+| Property | Type | Description
+|------.------------|--------------------|-------------------------------------------
+| `project` | *String* | Natron project file name
+| `input` | *String|Int|Null* | Extra options to pass on the ffmpeg command line
+| `output` | *String|Int|Null* | ffmpeg filter type; One of `complex`, `audio` or `video`
+| `framescale` | *Float* | Ratio of output frames to input files, 2.0=twice as many out as in=half speed
+
+**executor**
+
+| Property | Type | Description
+|------.------------|--------------------|-------------------------------------------
+| `set` | *Array* | Define variables
+| `script` | *Array* | Define commands
+| `set/%/value` | *String* | Set variable % to value.
+| `set/%/escape` | *Bool* | If true, the resulting vriable will be escaped
+| `script/%/info` | *String* | Info about what this step is doing
+| `script/%/exec` | *String* | Command to execute
+| `script/%/parse` | *Map* | Parse output from command, see docs for plugin
+
+
+## Parameters
+
+All parameters must specify `label` and `type`. The remaining keys are depending on the
+type of parameter.
+
+**float**
+
+Float parameters need to specify `min`, `max`, `default` and optionally `step`.
+
+
+## Examples
+
+### ffmpeg
+
+ preset:
+ name: Normalize audio level
+ group: ffmpeg/audio
+ plugin: ffmpeg
+ props:
+ filter: "dynaudnorm=m={maxgain}:s={compress}"
+ extra: "-c:v copy"
+ type: complex
+ params:
+ compress: { label:"Compression factor", type:float, min:0.0, max:30.0, default:0.0 }
+ maxgain: { label:"Max gain factor", type:float, min:0.0, max:100.0, default:10.0 }
+
+### natron
+
+ preset:
+ name: Apply a CCTV look to the video
+ group: natron
+ plugin: natron
+ props:
+ project: natron-cctv.ntp
+ reader: Reader1
+ writer: Writer1
+
+### executor
+
+ preset:
+ name: Stabilize video clip (two-pass)
+ group: video
+ plugin: executor
+ props:
+ set:
+ inputtrf: { value:"{%uinput}.trf", escape:true }
+ script:
+ analyze:
+ info: Getting stabilization vectors
+ exec: "transcode -i {%input} -J stabilize"
+ parse:
+ from: 'stderr'
+ regex: '/encoding frames \[0-([0-9]+?)\],\s+([0-9\.]+?) fps/'
+ frame:1
+ eta:2
+ stabilize:
+ info: Stabilizing video
+ exec: "transcode -i {%input} -o {%output} -J transform -y xvid"
+ parse:
+ from: 'stderr'
+ regex: '/encoding frames \[0-([0-9]+?)\],\s+([0-9\.]+?) fps/'
+ frame:1
+ eta:2
+ cleanup:
+ exec: "rm {%inputtrf}"
diff --git a/README.md b/README.md
index 7a380f3..ac063c6 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,12 @@ Natron pipeline.
## Usage
- vfxapply [-i ] [-o