First draft
diff --git a/jww_test.go b/jww_test.go
new file mode 100644
index 0000000..4b122d5
--- /dev/null
+++ b/jww_test.go
@@ -0,0 +1,49 @@
+// Copyright © 2014 Steve Francia <spf@spf13.com>.
+//
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+package jwalterweatherman
+
+import (
+    "bytes"
+    "github.com/stretchr/testify/assert"
+    "testing"
+)
+
+func TestLevels(t *testing.T) {
+    SetOutLevel(LevelError)
+    assert.Equal(t, OutLevel(), LevelError)
+    SetLogLevel(LevelCritical)
+    assert.Equal(t, LogLevel(), LevelCritical)
+    assert.NotEqual(t, OutLevel(), LevelCritical)
+    SetOutLevel(LevelWarn)
+    assert.Equal(t, OutLevel(), LevelWarn)
+}
+
+func TestDefaultLogging(t *testing.T) {
+    outputBuf := new(bytes.Buffer)
+    logBuf := new(bytes.Buffer)
+    LogHandle = logBuf
+    OutHandle = outputBuf
+
+    SetOutLevel(LevelInfo)
+    SetLogLevel(LevelWarn)
+
+    CRITICAL.Println("critical err")
+    ERROR.Println("an error")
+    WARN.Println("a warning")
+    INFO.Println("information")
+    DEBUG.Println("debugging info")
+
+    assert.Contains(t, logBuf.String(), "critical err")
+    assert.Contains(t, logBuf.String(), "an error")
+    assert.Contains(t, logBuf.String(), "information")
+    assert.Contains(t, logBuf.String(), "a warning")
+    assert.NotContains(t, logBuf.String(), "debugging info")
+    assert.Contains(t, outputBuf.String(), "critical err")
+    assert.Contains(t, outputBuf.String(), "an error")
+    assert.Contains(t, outputBuf.String(), "information")
+    assert.NotContains(t, outputBuf.String(), "a warning")
+    assert.NotContains(t, outputBuf.String(), "debugging info")
+}
diff --git a/thatswhyyoualwaysleaveanote.go b/thatswhyyoualwaysleaveanote.go
new file mode 100644
index 0000000..2470578
--- /dev/null
+++ b/thatswhyyoualwaysleaveanote.go
@@ -0,0 +1,224 @@
+// Copyright © 2014 Steve Francia <spf@spf13.com>.
+//
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+package jwalterweatherman
+
+import (
+    "fmt"
+    "io"
+    "io/ioutil"
+    "log"
+    "os"
+)
+
+// Level describes the chosen log level between
+// debug and critical.
+type Level int
+
+//TRACE
+//DEBUG
+//INFO
+//WARN
+//ERROR
+//CRITICAL
+//FATAL
+
+type JWWLevel struct {
+    Handle io.Writer
+    Level  int
+    *log.Logger
+}
+
+type Feedback struct{}
+
+// Log levels to control the logging output.
+const (
+    LevelDebug Level = iota
+    LevelWarn
+    LevelInfo
+    LevelError
+    LevelCritical
+)
+
+var (
+    DEBUG          *log.Logger
+    WARN           *log.Logger
+    INFO           *log.Logger
+    LOG            *log.Logger
+    ERROR          *log.Logger
+    CRITICAL       *log.Logger
+    FEEDBACK       Feedback
+    DebugHandle    io.Writer = os.Stdout
+    WarnHandle     io.Writer = os.Stdout
+    InfoHandle     io.Writer = os.Stdout
+    ErrorHandle    io.Writer = os.Stdout
+    CriticalHandle io.Writer = os.Stdout
+    logLevel       Level     = LevelWarn // 1
+    outLevel       Level     = LevelInfo // 2
+    LogHandle      io.Writer = ioutil.Discard
+    OutHandle      io.Writer = os.Stdout
+    BothHandle     io.Writer = io.MultiWriter(LogHandle, OutHandle)
+)
+
+func init() {
+    SetOutLevel(LevelInfo)
+}
+
+func Initialize() {
+    initWriters()
+
+    DEBUG = log.New(DebugHandle,
+        "DEBUG: ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+
+    INFO = log.New(InfoHandle,
+        "INFO:  ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+
+    LOG = log.New(LogHandle,
+        "LOG:   ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+
+    WARN = log.New(WarnHandle,
+        "WARN:  ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+
+    ERROR = log.New(ErrorHandle,
+        "ERROR: ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+
+    CRITICAL = log.New(CriticalHandle,
+        "CRITICAL: ",
+        log.Ldate|log.Ltime|log.Lshortfile)
+}
+
+// Level returns the current log level.
+func LogLevel() Level {
+    return logLevel
+}
+
+func OutLevel() Level {
+    return outLevel
+}
+
+func levelCheck(level Level) Level {
+    switch {
+    case level <= LevelDebug:
+        return LevelDebug
+    case level >= LevelCritical:
+        return LevelCritical
+    default:
+        return level
+    }
+}
+
+// SetLevel switches to a new log level.
+func SetLogLevel(level Level) {
+    logLevel = levelCheck(level)
+    Initialize()
+}
+
+func SetLogFile(path string) {
+    file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
+    fmt.Println("Logging to", file.Name())
+    if err != nil {
+        CRITICAL.Println("Failed to open log file:", path, err)
+        os.Exit(-1)
+    }
+
+    LogHandle = file
+    Initialize()
+}
+
+func UseTempLogFile(prefix string) {
+    file, err := ioutil.TempFile(os.TempDir(), prefix)
+    if err != nil {
+        CRITICAL.Println(err)
+    }
+
+    fmt.Println("Logging to", file.Name())
+
+    LogHandle = file
+    Initialize()
+}
+
+func DiscardLogging() {
+    LogHandle = ioutil.Discard
+    Initialize()
+}
+
+func SetOutLevel(level Level) {
+    outLevel = levelCheck(level) // 1
+    Initialize()
+}
+
+// Don't use if you have manually set the Handles of the different levels as it will overwrite them.
+func initWriters() {
+    BothHandle = io.MultiWriter(LogHandle, OutHandle)
+    //DEBUG
+    if LevelDebug < outLevel && LevelDebug < logLevel {
+        DebugHandle = ioutil.Discard
+    } else if LevelDebug >= outLevel && LevelDebug >= logLevel {
+        DebugHandle = BothHandle
+    } else if LevelDebug >= outLevel && LevelDebug < logLevel {
+        DebugHandle = OutHandle
+    } else {
+        DebugHandle = LogHandle
+    }
+
+    //WARN
+    if LevelWarn < outLevel && LevelWarn < logLevel {
+        WarnHandle = ioutil.Discard
+    } else if LevelWarn >= outLevel && LevelWarn >= logLevel {
+        WarnHandle = BothHandle
+    } else if LevelWarn >= outLevel && LevelWarn < logLevel {
+        WarnHandle = OutHandle
+    } else {
+        WarnHandle = LogHandle
+    }
+
+    //INFO
+    if LevelInfo < outLevel && LevelInfo < logLevel {
+        InfoHandle = ioutil.Discard
+    } else if LevelInfo >= outLevel && LevelInfo >= logLevel {
+        InfoHandle = BothHandle
+    } else if LevelInfo >= outLevel && LevelInfo < logLevel {
+        InfoHandle = OutHandle
+    } else {
+        InfoHandle = LogHandle
+    }
+
+    //ERROR
+    if LevelError < outLevel && LevelError < logLevel {
+        ErrorHandle = ioutil.Discard
+    } else if LevelError >= outLevel && LevelError >= logLevel {
+        ErrorHandle = BothHandle
+    } else if LevelError >= outLevel && LevelError < logLevel {
+        ErrorHandle = OutHandle
+    } else {
+        ErrorHandle = LogHandle
+    }
+
+    //CRITICAL
+    if LevelCritical < outLevel && LevelCritical < logLevel {
+        CriticalHandle = ioutil.Discard
+    } else if LevelCritical >= outLevel && LevelCritical >= logLevel {
+        CriticalHandle = BothHandle
+    } else if LevelCritical >= outLevel && LevelCritical < logLevel {
+        CriticalHandle = OutHandle
+    } else {
+        CriticalHandle = LogHandle
+    }
+}
+
+func (fb *Feedback) Println(v ...interface{}) {
+    fmt.Println(v...)
+    LOG.Println(v...)
+}
+
+func (fb *Feedback) Printf(format string, v ...interface{}) {
+    fmt.Printf(format, v...)
+    LOG.Printf(format, v...)
+}