diff --git a/logging/config/presets/instructions.go b/logging/config/presets/instructions.go
index 9077d9e8242dc19423e5f1faf913ca97a9e650ec..91065d2faa9effbfc8bf796175b7fa7eb691deae 100644
--- a/logging/config/presets/instructions.go
+++ b/logging/config/presets/instructions.go
@@ -13,13 +13,14 @@ import (
 // Returning the new subroot from which to apply any further Presets.
 // When chained together in a pre-order instructions can be composed to form an entire Sink tree.
 type Instruction struct {
-	name string
-	desc string
+	name  string
+	desc  string
+	nargs int
 	// The builder for the Instruction is a function that may modify the stack or ops string. Typically
 	// by mutating the sink at the top of the stack and may move the cursor or by pushing child sinks
 	// to the stack. The builder may also return a modified ops slice whereby it may insert Instruction calls
 	// acting as a macro or consume ops as arguments.
-	builder func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error)
+	builder func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error)
 }
 
 func (i Instruction) Name() string {
@@ -37,88 +38,113 @@ const (
 	Stderr     = "stderr"
 	Stdout     = "stdout"
 	Terminal   = "terminal"
+	JSON       = "json"
 	Up         = "up"
 	Down       = "down"
+	File       = "file"
 )
 
 var instructions = []Instruction{
 	{
 		name: Up,
 		desc: "Ascend the sink tree by travelling up the stack to the previous sink recorded on the stack",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
-			return pop(stack), ops, nil
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+			return pop(stack), nil
 		},
 	},
 	{
 		name: Down,
 		desc: "Descend the sink tree by inserting a sink as a child to the current sink and adding it to the stack",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
-			return push(stack, config.Sink()), ops, nil
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+			return push(stack, config.Sink()), nil
 		},
 	},
 	{
 		name: Minimal,
 		desc: "A generally less chatty log output, follow with output options",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			return push(stack,
-					config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)),
-					config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
-						structure.ChannelKey, structure.InfoChannelName)),
-					config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
-						structure.ComponentKey, "Tendermint",
-						"module", "p2p",
-						"module", "mempool"))),
-				ops, nil
+				config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)),
+				config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
+					structure.ChannelKey, structure.InfoChannelName)),
+				config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
+					structure.ComponentKey, "Tendermint",
+					"module", "p2p",
+					"module", "mempool"))), nil
 		},
 	},
 	{
 		name: IncludeAny,
 		desc: "Establish an 'include when any predicate matches' filter transform at this this sink",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			sink := peek(stack)
 			ensureFilter(sink)
 			sink.Transform.FilterConfig.FilterMode = config.IncludeWhenAnyMatches
-			return stack, ops, nil
+			return stack, nil
 		},
 	},
 	{
 		name: Info,
 		desc: "Add a filter predicate to match the Info logging channel",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			sink := peek(stack)
 			ensureFilter(sink)
 			sink.Transform.FilterConfig.AddPredicate(structure.ChannelKey, structure.InfoChannelName)
-			return stack, ops, nil
+			return stack, nil
 		},
 	},
 	{
 		name: Stdout,
 		desc: "Use Stdout output for this sink",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
 			sink.Output.OutputType = config.Stdout
-			return stack, ops, nil
+			return stack, nil
 		},
 	},
 	{
 		name: Stderr,
 		desc: "Use Stderr output for this sink",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
 			sink.Output.OutputType = config.Stderr
-			return stack, ops, nil
+			return stack, nil
 		},
 	},
 	{
 		name: Terminal,
 		desc: "Use the the terminal output format for this sink",
-		builder: func(stack []*config.SinkConfig, ops []string) ([]*config.SinkConfig, []string, error) {
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
 			sink.Output.Format = loggers.TerminalFormat
-			return stack, ops, nil
+			return stack, nil
+		},
+	},
+	{
+		name: JSON,
+		desc: "Use the the terminal output format for this sink",
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+			sink := peek(stack)
+			ensureOutput(sink)
+			sink.Output.Format = loggers.JSONFormat
+			return stack, nil
+		},
+	},
+	{
+		name:  File,
+		desc:  "Use the the terminal output format for this sink",
+		nargs: 1,
+		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+			sink := peek(stack)
+			ensureOutput(sink)
+			sink.Output.OutputType = config.File
+			sink.Output.FileConfig = &config.FileConfig{
+				Path: args[0],
+			}
+			return stack, nil
 		},
 	},
 }
@@ -149,16 +175,26 @@ func Describe(name string) string {
 func BuildSinkConfig(ops ...string) (*config.SinkConfig, error) {
 	stack := []*config.SinkConfig{config.Sink()}
 	var err error
+	pos := 0
 	for len(ops) > 0 {
 		// Keep applying instructions until their are no ops left
-		preset, ok := instructionsMap[ops[0]]
+		instruction, ok := instructionsMap[ops[0]]
 		if !ok {
 			return nil, fmt.Errorf("could not find logging preset '%s'", ops[0])
 		}
-		stack, ops, err = preset.builder(stack, ops[1:])
+		// pop instruction name
+		ops = ops[1:]
+		if len(ops) < instruction.nargs {
+			return nil, fmt.Errorf("did not have enough arguments for instruction %s at position %v "+
+				"(requires %v arguments)", instruction.name, pos, instruction.nargs)
+		}
+		stack, err = instruction.builder(stack, ops[:instruction.nargs])
 		if err != nil {
 			return nil, err
 		}
+		// pop instruction args
+		ops = ops[instruction.nargs:]
+		pos++
 	}
 	return stack[0], nil
 }
diff --git a/logging/config/presets/instructions_test.go b/logging/config/presets/instructions_test.go
index adbfe1b0a5fd4bc6863c372c4a61a60a33f0f25c..c8398cc5c76183f09ae40f6480ff738272ae2df7 100644
--- a/logging/config/presets/instructions_test.go
+++ b/logging/config/presets/instructions_test.go
@@ -39,3 +39,13 @@ func TestMinimalPreset(t *testing.T) {
 	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
 	assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink))
 }
+
+func TestFileOutput(t *testing.T) {
+	path := "foo.log"
+	builtSink, err := BuildSinkConfig(Down, File, path, JSON)
+	require.NoError(t, err)
+	expectedSink := config.Sink().
+		AddSinks(config.Sink().SetOutput(config.FileOutput(path).SetFormat(loggers.JSONFormat)))
+	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
+	assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink))
+}