ADDED   src/0dev.org/commands/pdc/main.go
Index: src/0dev.org/commands/pdc/main.go
==================================================================
--- /dev/null
+++ src/0dev.org/commands/pdc/main.go
@@ -0,0 +1,77 @@
+package main
+
+import (
+	predictor "0dev.org/predictor"
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+)
+
+func main() {
+	switch {
+	case len(os.Args) == 1:
+		os.Exit(compress(os.Stdout, os.Stdin))
+	case len(os.Args) == 2 && os.Args[1] == "-d":
+		os.Exit(decompress(os.Stdout, os.Stdin))
+	default:
+		fmt.Fprintln(os.Stdout, "Usage: pdc [-d]")
+	}
+}
+
+// Compress the data from the given io.Reader and write it to the given io.Writer
+// I/O is buffered for better performance
+func compress(output io.Writer, input io.Reader) int {
+	var (
+		err        error
+		buffer     *bufio.Writer = bufio.NewWriter(output)
+		compressor io.Writer     = predictor.Compressor(buffer)
+	)
+
+	_, err = io.Copy(compressor, bufio.NewReader(input))
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Error while compressing.\n", err)
+		return 1
+	}
+
+	// Flush the compressor
+	_, err = compressor.Write(nil)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Error while flushing compresssor buffer.\n", err)
+		return 1
+	}
+
+	// Flush the buffer
+	err = buffer.Flush()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Error while flushing output buffer.\n", err)
+		return 1
+	}
+
+	return 0
+}
+
+// Decompress the data from the given io.Reader and write it to the given io.Writer
+// I/O is buffered for better performance
+func decompress(output io.Writer, input io.Reader) int {
+	var (
+		err          error
+		buffer       *bufio.Writer = bufio.NewWriter(output)
+		decompressor io.Reader     = predictor.Decompressor(input)
+	)
+
+	_, err = io.Copy(buffer, bufio.NewReader(decompressor))
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Error while decompressing.\n", err)
+		return 1
+	}
+
+	// Flush
+	err = buffer.Flush()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Error while flushing output buffer.\n", err)
+		return 1
+	}
+
+	return 0
+}

Index: src/0dev.org/commands/plaindiff/main.go
==================================================================
--- src/0dev.org/commands/plaindiff/main.go
+++ src/0dev.org/commands/plaindiff/main.go
@@ -8,11 +8,11 @@
 	"hash/fnv"
 	"io"
 	"os"
 )
 
-const usage = "Usage: plaindiff <file1> <file2>"
+const usage = "Usage: plaindiff <file1> <file2>\n"
 
 func main() {
 	var args []string = os.Args
 	if len(args) != 3 {
 		os.Stderr.WriteString(usage)

Index: src/0dev.org/predictor/predictor.go
==================================================================
--- src/0dev.org/predictor/predictor.go
+++ src/0dev.org/predictor/predictor.go
@@ -11,20 +11,27 @@
 	buffer [1 << 3]byte
 	input  []byte
 	hash   uint16
 }
 
-// Returns a closure over the provided writer that compresses data when called.
+type compressor func([]byte) error
+
+func (w compressor) Write(data []byte) (int, error) {
+	return len(data), w(data)
+}
+
+// Returns an io.Writer implementation that wraps the provided io.Writer
+// and compresses data according to the predictor algorithm
 //
 // It can buffer data as the predictor mandates 8-byte blocks with a header.
 // A call with no data will force a flush.
-func Compressor(writer io.Writer) func([]byte) error {
+func Compressor(writer io.Writer) io.Writer {
 	var ctx context
 	ctx.input = ctx.buffer[:0]
 
 	// Forward declaration as it is required for recursion
-	var write func(data []byte) error
+	var write compressor
 
 	write = func(data []byte) error {
 		var (
 			blockSize    int = 8
 			bufferLength int = len(ctx.input)
@@ -101,22 +108,25 @@
 	}
 
 	return write
 }
 
-type reader func([]byte) (int, error)
+// A function type alias so that it can have methods attached to it
+type decompressor func([]byte) (int, error)
 
-func (r reader) Read(output []byte) (int, error) {
+// Required to implement io.Reader
+func (r decompressor) Read(output []byte) (int, error) {
 	return r(output)
 }
 
-// TODO - document
+// Returns an io.Reader implementation that wraps the provided io.Reader
+// and decompresses data according to the predictor algorithm
 func Decompressor(wrapped io.Reader) io.Reader {
 	var ctx context
 	ctx.input = ctx.buffer[:0]
 
-	return reader(func(output []byte) (int, error) {
+	return decompressor(func(output []byte) (int, error) {
 		var (
 			err       error
 			flags     byte
 			readCount int
 		)

Index: src/0dev.org/predictor/predictor_test.go
==================================================================
--- src/0dev.org/predictor/predictor_test.go
+++ src/0dev.org/predictor/predictor_test.go
@@ -29,16 +29,16 @@
 		buf bytes.Buffer
 		err error
 	)
 
 	out := Compressor(&buf)
-	err = out(input)
+	_, err = out.Write(input)
 	if err != nil {
 		t.Error(err)
 	}
 
-	err = out(nil)
+	_, err = out.Write(nil)
 	if err != nil {
 		t.Error(err)
 	}
 
 	result := buf.Bytes()
@@ -109,11 +109,11 @@
 	for len(data) > 0 {
 		if step <= len(data) {
 
 			trace = append(trace, data[:step]...)
 
-			err = compressor(data[:step])
+			_, err = compressor.Write(data[:step])
 			if err != nil {
 				return err
 			}
 			data = data[step:]
 		} else {
@@ -120,11 +120,11 @@
 			step = len(data)
 		}
 	}
 
 	// Flush the compressor
-	err = compressor(nil)
+	_, err = compressor.Write(nil)
 	if err != nil {
 		return err
 	}
 
 	// Attempt to decompress the data