custom errors
diff --git a/tfexec/errors.go b/tfexec/errors.go
new file mode 100644
index 0000000..96e4913
--- /dev/null
+++ b/tfexec/errors.go
@@ -0,0 +1,74 @@
+package tfexec
+
+import (
+	"fmt"
+	"regexp"
+)
+
+func parseError(stderr string) error {
+	switch {
+	// case ErrTerraformNotFound.regexp.MatchString(stderr):
+	// return ErrTerraformNotFound
+	case regexp.MustCompile(usageRegexp).MatchString(stderr):
+		return &ErrCLIUsage{stderr: stderr}
+	case regexp.MustCompile(`Error: Could not satisfy plugin requirements`).MatchString(stderr):
+		return &ErrNoInit{stderr: stderr}
+	case regexp.MustCompile(`Error: No configuration files`).MatchString(stderr):
+		return &ErrNoConfig{stderr: stderr}
+	default:
+		return &Err{stderr: stderr}
+	}
+}
+
+type ErrNoSuitableBinary struct {
+	err error
+}
+
+func (e *ErrNoSuitableBinary) Error() string {
+	return fmt.Sprintf("no suitable terraform binary could be found: %s", e.err.Error())
+}
+
+// Not yet implemented.
+// Intended for use when the detected Terraform version is not compatible with the command or flags being used in this invocation.
+type ErrVersionMismatch struct{}
+
+type ErrNoInit struct {
+	stderr string
+}
+
+func (e *ErrNoInit) Error() string {
+	return e.stderr
+}
+
+type ErrNoConfig struct {
+	stderr string
+}
+
+func (e *ErrNoConfig) Error() string {
+	return e.stderr
+}
+
+// Terraform CLI indicates usage errors in three different ways: either
+// 1. Exit 1, with a custom error message on stderr.
+// 2. Exit 1, with command usage logged to stderr.
+// 3. Exit 127, with command usage logged to stdout.
+// Currently cases 1 and 2 are handled.
+// TODO KEM: Handle exit 127 case. How does this work on non-Unix platforms?
+type ErrCLIUsage struct {
+	stderr string
+}
+
+var usageRegexp = `Too many command line arguments|^Usage: .*Options:.*|Error: Invalid -\d+ option`
+
+func (e *ErrCLIUsage) Error() string {
+	return e.stderr
+}
+
+// catchall error
+type Err struct {
+	stderr string
+}
+
+func (e *Err) Error() string {
+	return e.stderr
+}
diff --git a/tfexec/main.go b/tfexec/main.go
index d601e2e..627c8ba 100644
--- a/tfexec/main.go
+++ b/tfexec/main.go
@@ -4,14 +4,13 @@
 	"fmt"
 	"os"
 	"os/exec"
-	"runtime"
 )
 
 // FindTerraform attempts to find a Terraform CLI executable.
 //
 // As a first preference it will look for the environment variable
 // TFEXEC_TERRAFORM_PATH and return its value. If that variable is not set, it will
-// look in PATH for a program named "terraform.exe" on Windows, or "terraform" otherwise,
+// look in PATH for a program named "terraform",
 // and, if one is found, return its absolute path.
 func FindTerraform() (string, error) {
 	if p := os.Getenv("TFEXEC_TERRAFORM_PATH"); p != "" {
@@ -20,10 +19,6 @@
 
 	execName := "terraform"
 
-	if runtime.GOOS == "windows" {
-		execName = "terraform.exe"
-	}
-
 	p, err := exec.LookPath(execName)
 	if err != nil {
 		return "", fmt.Errorf("terraform executable could not be found: %s", err)
diff --git a/tfexec/terraform.go b/tfexec/terraform.go
index 4eb1123..d501889 100644
--- a/tfexec/terraform.go
+++ b/tfexec/terraform.go
@@ -4,10 +4,8 @@
 	"bytes"
 	"context"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"os"
-	"os/exec"
 	"strings"
 
 	tfjson "github.com/hashicorp/terraform-json"
@@ -36,7 +34,7 @@
 	if execPath == "" {
 		execPath, err = FindTerraform()
 		if err != nil {
-			return nil, err
+			return nil, &ErrNoSuitableBinary{err: err}
 		}
 
 	}
@@ -48,7 +46,7 @@
 
 	execVersion, err := tf.version()
 	if err != nil {
-		return nil, fmt.Errorf("error running 'terraform version': %s", err)
+		return nil, &ErrNoSuitableBinary{err: fmt.Errorf("error running 'terraform version': %s", err)}
 	}
 
 	tf.execVersion = execVersion
@@ -92,10 +90,6 @@
 		return "", fmt.Errorf("%s, %s", err, errBuf.String())
 	}
 
-	// fmt.Println(outBuf.String())
-
-	// parse it
-
 	return outBuf.String(), nil
 }
 
@@ -182,7 +176,7 @@
 
 	err := initCmd.Run()
 	if err != nil {
-		return errors.New(errBuf.String())
+		return parseError(errBuf.String())
 	}
 
 	return nil
@@ -268,7 +262,7 @@
 
 	err := applyCmd.Run()
 	if err != nil {
-		return errors.New(errBuf.String())
+		return parseError(errBuf.String())
 	}
 
 	return nil
@@ -350,7 +344,7 @@
 
 	err := destroyCmd.Run()
 	if err != nil {
-		return errors.New(errBuf.String())
+		return parseError(errBuf.String())
 	}
 
 	return nil
@@ -429,7 +423,7 @@
 
 	err := planCmd.Run()
 	if err != nil {
-		return errors.New(errBuf.String())
+		return parseError(errBuf.String())
 	}
 
 	return nil
@@ -541,7 +535,7 @@
 
 	err := outputCmd.Run()
 	if err != nil {
-		return nil, err
+		return nil, parseError(err.Error())
 	}
 
 	err = json.Unmarshal(outBuf.Bytes(), outputs)
@@ -565,10 +559,7 @@
 
 	err := showCmd.Run()
 	if err != nil {
-		if tErr, ok := err.(*exec.ExitError); ok {
-			err = fmt.Errorf("terraform failed: %s\n\nstderr:\n%s", tErr.ProcessState.String(), errBuf.String())
-		}
-		return nil, err
+		return nil, parseError(errBuf.String())
 	}
 
 	err = json.Unmarshal(outBuf.Bytes(), &ret)
@@ -597,10 +588,7 @@
 
 	err := schemaCmd.Run()
 	if err != nil {
-		if tErr, ok := err.(*exec.ExitError); ok {
-			err = fmt.Errorf("terraform failed: %s\n\nstderr:\n%s", tErr.ProcessState.String(), errBuf.String())
-		}
-		return nil, err
+		return nil, parseError(errBuf.String())
 	}
 
 	err = json.Unmarshal(outBuf.Bytes(), ret)
diff --git a/tfexec/terraform_test.go b/tfexec/terraform_test.go
index 45d371e..c7a6a79 100644
--- a/tfexec/terraform_test.go
+++ b/tfexec/terraform_test.go
@@ -316,18 +316,12 @@
 
 	err = copyFile(filepath.Join(testFixtureDir, testTerraformStateFileName), filepath.Join(td, testTerraformStateFileName))
 
-	// This test will break if the error output of `terraform init`
-	// changes significantly. We tolerate this brittleness as a poor
-	// man's canary for significant changes to Terraform CLI.
-	// FIXME: Parse this in the actual command and return ErrNoInit
-	expected := "Error: Could not satisfy plugin requirements"
-
 	_, err = tf.StateShow(context.Background())
 	if err == nil {
 		t.Fatal("expected Show to error, but it did not")
 	} else {
-		if !strings.Contains(err.Error(), expected) {
-			t.Fatalf("expected error %s to contain %s", err, expected)
+		if _, ok := err.(*ErrNoInit); !ok {
+			t.Fatalf("expected error %s to be ErrNoInit", err)
 		}
 	}