diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..efdb3a1
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "spec"]
+	path = spec
+	url = https://github.com/catseye/Funge-98
+[submodule "mycology"]
+	path = mycology
+	url = https://github.com/Deewiant/Mycology
diff --git a/cmd/headless_interpreter/main.go b/cmd/headless_interpreter/main.go
index 9bed538..8bf97c4 100644
--- a/cmd/headless_interpreter/main.go
+++ b/cmd/headless_interpreter/main.go
@@ -37,7 +37,8 @@ func main() {
 		fmt.Printf("Failed to load file %s : %+v", *filename, err)
 		os.Exit(3)
 	}
-
-	v := interpreter.NewInterpreter(f, pointer.NewPointer()).Run()
+	p := pointer.NewPointer()
+	p.Argv = []string{*filename}
+	v := interpreter.NewInterpreter(f, p).Run()
 	os.Exit(v)
 }
diff --git a/go.mod b/go.mod
index 4dea3d5..718a815 100644
--- a/go.mod
+++ b/go.mod
@@ -6,8 +6,6 @@ require github.com/stretchr/testify v1.7.0
 
 require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/pkg/term v1.1.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 )
diff --git a/go.sum b/go.sum
index edc2e45..c221f64 100644
--- a/go.sum
+++ b/go.sum
@@ -1,15 +1,11 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk=
-github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
-golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/mycology b/mycology
new file mode 160000
index 0000000..3787e42
--- /dev/null
+++ b/mycology
@@ -0,0 +1 @@
+Subproject commit 3787e42c3d4f0b735a09129a205e3e4df848558c
diff --git a/pkg/field/utils.go b/pkg/field/utils.go
index 4c4774c..1bd2b2b 100644
--- a/pkg/field/utils.go
+++ b/pkg/field/utils.go
@@ -96,3 +96,7 @@ func (f *Field) Set(x, y, v int) {
 		}
 	}
 }
+
+func (f Field) Dump() (int, int, int, int) {
+	return f.x, f.y, f.lx, f.ly
+}
diff --git a/pkg/field/utils_test.go b/pkg/field/utils_test.go
index 9c1f7c7..837f9fb 100644
--- a/pkg/field/utils_test.go
+++ b/pkg/field/utils_test.go
@@ -329,3 +329,9 @@ func TestGetAndSetOnEmptyLines(t *testing.T) {
 	field.Set(0, -1, 'c')
 	require.Equal(t, &f, field)
 }
+
+func TestDump(t *testing.T) {
+	// nothing to test really
+	f := Field{}
+	f.Dump()
+}
diff --git a/pkg/pointer/exec.go b/pkg/pointer/exec.go
index f7fcf8f..448e1e1 100644
--- a/pkg/pointer/exec.go
+++ b/pkg/pointer/exec.go
@@ -2,6 +2,9 @@ package pointer
 
 import (
 	"log"
+	"os"
+	"time"
+	"unsafe"
 
 	"git.adyxax.org/adyxax/gofunge/pkg/field"
 )
@@ -41,12 +44,21 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) {
 	switch c {
 	case '@':
 		return true, nil
+	case 'z':
 	case '#':
 		p.Step(*f)
 	case 'j':
 		n := p.ss.head.Pop()
-		for j := 0; j < n; j++ {
-			p.Step(*f)
+		if n > 0 {
+			for j := 0; j < n; j++ {
+				p.Step(*f)
+			}
+		} else {
+			p.Reverse()
+			for j := 0; j < -n; j++ {
+				p.Step(*f)
+			}
+			p.Reverse()
 		}
 	case 'q':
 		v := p.ss.head.Pop()
@@ -54,13 +66,27 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) {
 	case 'k':
 		n := p.ss.head.Pop()
 		c = p.StepAndGet(*f)
+		steps := 1
 		for jumpingMode := false; jumpingMode || c == ' ' || c == ';'; c = p.StepAndGet(*f) {
+			steps += 1
 			if c == ';' {
 				jumpingMode = !jumpingMode
 			}
 		}
-		for j := 0; j < n; j++ {
-			p.eval(c, f)
+		if n > 0 {
+			// we need to reverse that step
+			p.Reverse()
+			for i := 0; i < steps; i++ {
+				p.Step(*f)
+			}
+			p.Reverse()
+			if c != ' ' && c != ';' {
+				if n > 0 {
+					for i := 0; i < n; i++ {
+						p.eval(c, f)
+					}
+				}
+			}
 		}
 	case '!':
 		v := p.ss.head.Pop()
@@ -140,9 +166,13 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) {
 	case '{':
 		p.ss.Begin(p)
 	case '}':
-		p.ss.End(p)
+		if p.ss.End(p) {
+			p.Reverse()
+		}
 	case 'u':
-		p.ss.Under()
+		if p.ss.Under() {
+			p.Reverse()
+		}
 	case 'g':
 		y, x := p.ss.head.Pop(), p.ss.head.Pop()
 		p.ss.head.Push(f.Get(x+p.sox, y+p.soy))
@@ -157,6 +187,123 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) {
 		p.ss.head.Push(p.DecimalInput())
 	case '~':
 		p.ss.head.Push(p.CharacterInput())
+	case 'y':
+		n := p.ss.head.Pop()
+		if n > 22+p.ss.height {
+			n = n - 20
+			if p.ss.head.height <= n {
+				p.ss.head.Push(0)
+			} else {
+				p.ss.head.Push(p.ss.head.data[p.ss.head.height-n])
+			}
+			return
+		}
+		now := time.Now()
+		x, y, lx, ly := f.Dump()
+		const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64
+		heights := make([]int, p.ss.height)
+		s := p.ss.head
+		for i := p.ss.height - 1; i >= 0; i-- {
+			heights[i] = s.height
+			s = s.next
+		}
+		if n <= 0 {
+			for _, e := range os.Environ() {
+				p.ss.head.Push(0)
+				for i := len(e) - 1; i >= 0; i-- {
+					p.ss.head.Push(int(e[i]))
+				}
+			}
+		}
+		if n <= 0 {
+			p.ss.head.Push(0)
+			p.ss.head.Push(0)
+			for i := len(p.Argv) - 1; i >= 0; i-- {
+				p.ss.head.Push(0)
+				for j := len(p.Argv[i]) - 1; j >= 0; j-- {
+					p.ss.head.Push(int(p.Argv[i][j]))
+				}
+			}
+		}
+		if (n > 22 && n <= 22+p.ss.height) || n <= 0 {
+			for i := 0; i < len(heights); i++ {
+				p.ss.head.Push(heights[i])
+			}
+		}
+		if n == 22 || n <= 0 {
+			p.ss.head.Push(p.ss.height)
+		}
+		if n == 21 || n <= 0 {
+			p.ss.head.Push((now.Hour() * 256 * 256) + (now.Minute() * 256) + now.Second())
+		}
+		if n == 20 || n <= 0 {
+			p.ss.head.Push(((now.Year() - 1900) * 256 * 256) + (int(now.Month()) * 256) + now.Day())
+		}
+		if n == 19 || n <= 0 {
+			p.ss.head.Push(lx + x)
+		}
+		if n == 18 || n <= 0 {
+			p.ss.head.Push(ly + y)
+		}
+		if n == 17 || n <= 0 {
+			p.ss.head.Push(x)
+		}
+		if n == 16 || n <= 0 {
+			p.ss.head.Push(y)
+		}
+		if n == 15 || n <= 0 {
+			p.ss.head.Push(p.sox)
+		}
+		if n == 14 || n <= 0 {
+			p.ss.head.Push(p.soy)
+		}
+		if n == 13 || n <= 0 {
+			p.ss.head.Push(p.dx)
+		}
+		if n == 12 || n <= 0 {
+			p.ss.head.Push(p.dy)
+		}
+		if n == 11 || n <= 0 {
+			p.ss.head.Push(p.x)
+		}
+		if n == 10 || n <= 0 {
+			p.ss.head.Push(p.y)
+		}
+		if n == 9 || n <= 0 {
+			p.ss.head.Push(0)
+		}
+		if n == 8 || n <= 0 {
+			p.ss.head.Push(*((*int)(unsafe.Pointer(p))))
+		}
+		if n == 7 || n <= 0 {
+			p.ss.head.Push(2)
+		}
+		if n == 6 || n <= 0 {
+			p.ss.head.Push('/')
+		}
+		if n == 5 || n <= 0 {
+			p.ss.head.Push(0) // TODO update when implementing =
+		}
+		if n == 4 || n <= 0 {
+			p.ss.head.Push(1)
+		}
+		if n == 3 || n <= 0 {
+			p.ss.head.Push(1048576)
+		}
+		if n == 2 || n <= 0 {
+			p.ss.head.Push(uintSize / 8)
+		}
+		if n == 1 || n <= 0 {
+			p.ss.head.Push(0b00000) // TODO update when implementing t, i, o and =
+		}
+	case 'i':
+		log.Fatalf("Non implemented instruction code %d : %c", c, c)
+	case 'o':
+		log.Fatalf("Non implemented instruction code %d : %c", c, c)
+	case '=':
+		log.Fatalf("Non implemented instruction code %d : %c", c, c)
+	case 't':
+		log.Fatalf("Non implemented instruction code %d : %c", c, c)
 	default:
 		handled = false
 	}
@@ -168,7 +315,7 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) {
 		case c >= 'a' && c <= 'f':
 			p.ss.head.Push(c - 'a' + 10)
 		default:
-			log.Fatalf("Non implemented instruction code %d : %c", c, c)
+			p.Redirect('r')
 		}
 	}
 	return
diff --git a/pkg/pointer/intput-output.go b/pkg/pointer/intput-output.go
index cc7533e..ac58d44 100644
--- a/pkg/pointer/intput-output.go
+++ b/pkg/pointer/intput-output.go
@@ -4,8 +4,6 @@ import (
 	"fmt"
 	"log"
 	"os"
-
-	"github.com/pkg/term"
 )
 
 var defaultInputLastChar *int = nil
@@ -16,13 +14,6 @@ func DefaultCharacterInput() int {
 		defaultInputLastChar = nil
 		return c
 	}
-	t, err := term.Open("/dev/stdin")
-	if err != nil {
-		log.Fatalf("Could not open stdin: %+v", err)
-	}
-	defer t.Close()
-	defer t.Restore()
-	term.RawMode(t)
 	b := make([]byte, 1)
 	i, err := os.Stdin.Read(b)
 	if err != nil {
diff --git a/pkg/pointer/pointer.go b/pkg/pointer/pointer.go
index 2eea79d..d9a6b3d 100644
--- a/pkg/pointer/pointer.go
+++ b/pkg/pointer/pointer.go
@@ -31,6 +31,8 @@ type Pointer struct {
 	DecimalInput    InputFunction
 	CharacterOutput OutputFunction
 	DecimalOutput   OutputFunction
+	// command line arguments
+	Argv []string
 }
 
 func NewPointer() *Pointer {
diff --git a/pkg/pointer/stack-stack.go b/pkg/pointer/stack-stack.go
index 2f57b05..404542c 100644
--- a/pkg/pointer/stack-stack.go
+++ b/pkg/pointer/stack-stack.go
@@ -21,18 +21,27 @@ func (ss *StackStack) Begin(p *Pointer) {
 		np = -np
 	}
 	toss := &Stack{
-		size:   np,
-		height: np,
-		data:   make([]int, np),
-		next:   soss,
+		size: np,
+		data: make([]int, np),
+		next: soss,
 	}
 	ss.head = toss
-	max := n - soss.height
-	if max < 0 {
-		max = 0
-	}
-	for i := n - 1; i >= max; i-- {
-		toss.data[i] = soss.data[soss.height-n+i]
+	if n > 0 {
+		toss.height = n
+		elts := soss.height - n
+		if elts < 0 {
+			elts = soss.height
+		} else {
+			elts = n
+		}
+		for i := 1; i <= elts; i++ {
+			toss.data[toss.height-i] = soss.data[soss.height-i]
+		}
+		soss.height -= elts
+	} else if n < 0 {
+		for i := 0; i < np; i++ {
+			soss.Push(0)
+		}
 	}
 	x, y := p.GetStorageOffset()
 	soss.Push(x)
@@ -50,6 +59,12 @@ func (ss *StackStack) End(p *Pointer) (reflect bool) {
 	x := soss.Pop()
 	p.SetStorageOffset(x, y)
 	if n > 0 {
+		if n > ss.head.height {
+			for i := n; i > ss.head.height; i-- {
+				soss.Push(0)
+			}
+			n = ss.head.height
+		}
 		soss.height += n
 		if soss.size < soss.height {
 			soss.data = append(soss.data, make([]int, soss.height-soss.size)...)
@@ -58,7 +73,7 @@ func (ss *StackStack) End(p *Pointer) (reflect bool) {
 		for i := n; i > 0; i-- {
 			soss.data[soss.height-i] = ss.head.data[ss.head.height-i]
 		}
-	} else {
+	} else if n < 0 {
 		soss.height += n
 		if soss.height < 0 {
 			soss.height = 0
diff --git a/pkg/pointer/stack.go b/pkg/pointer/stack.go
index 1832dbb..ba51c7c 100644
--- a/pkg/pointer/stack.go
+++ b/pkg/pointer/stack.go
@@ -23,6 +23,9 @@ func (s *Stack) Clear() {
 func (s *Stack) Duplicate() {
 	if s.height > 0 {
 		s.Push(s.data[s.height-1])
+	} else {
+		s.Push(0)
+		s.Push(0)
 	}
 }
 
diff --git a/spec b/spec
new file mode 160000
index 0000000..7b4330d
--- /dev/null
+++ b/spec
@@ -0,0 +1 @@
+Subproject commit 7b4330df1a624c464f01c80090b60621ce5a330e