diff --git a/documentation/kyverno-cli.md b/documentation/kyverno-cli.md
index fbfeef9269..85ff9d3b7f 100644
--- a/documentation/kyverno-cli.md
+++ b/documentation/kyverno-cli.md
@@ -1,5 +1,4 @@
-<small>*[documentation](/README.md#documentation) / kyverno-cli*</small>
-
+<small>_[documentation](/README.md#documentation) / kyverno-cli_</small>
 
 # Kyverno CLI
 
@@ -40,39 +39,55 @@ yay -S kyverno-git
 
 Prints the version of kyverno used by the CLI.
 
-Example: 
+Example:
+
 ```
 kyverno version
 ```
 
 #### Validate
-Validates a policy, can validate multiple policy resource description files or even an entire folder containing policy resource description 
-files. Currently supports files with resource description in yaml.
+
+Validates a policy, can validate multiple policy resource description files or even an entire folder containing policy resource description
+files. Currently supports files with resource description in YAML.
 
 Example:
+
 ```
 kyverno validate /path/to/policy1.yaml /path/to/policy2.yaml /path/to/folderFullOfPolicies
 ```
 
 #### Apply
+
 Applies policies on resources, and supports applying multiple policies on multiple resources in a single command.
 Also supports applying the given policies to an entire cluster. The current kubectl context will be used to access the cluster.
- Will return results to stdout.
+Will return results to stdout.
 
 Apply to a resource:
-```
+
+```bash
 kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml
 ```
 
 Apply to all matching resources in a cluster:
-```
+
+```bash
 kyverno apply /path/to/policy.yaml --cluster > policy-results.txt
 ```
 
 Apply multiple policies to multiple resources:
-```
+
+```bash
 kyverno apply /path/to/policy1.yaml /path/to/folderFullOfPolicies --resource /path/to/resource1.yaml --resource /path/to/resource2.yaml --cluster
 ```
 
+##### Exit Codes
 
-<small>*Read Next >> [Sample Policies](/samples/README.md)*</small>
+The CLI exits with diffenent exit codes:
+
+| Message                               | Exit Code |
+| ------------------------------------- | --------- |
+| executes successfully                 | 0         |
+| one or more policy rules are violated | 1         |
+| policy validation failed              | 2         |
+
+<small>_Read Next >> [Sample Policies](/samples/README.md)_</small>
diff --git a/pkg/kyverno/apply/command.go b/pkg/kyverno/apply/command.go
index e9f0b71bb3..5aa92e33f2 100644
--- a/pkg/kyverno/apply/command.go
+++ b/pkg/kyverno/apply/command.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"os"
 	"regexp"
 	"time"
 
@@ -68,7 +69,8 @@ func Command() *cobra.Command {
 			for _, policy := range policies {
 				err := policy2.Validate(utils.MarshalPolicy(*policy), nil, true, openAPIController)
 				if err != nil {
-					return sanitizedError.New(fmt.Sprintf("Policy %v is not valid", policy.Name))
+					fmt.Printf("Policy %v is not valid\n", policy.Name)
+					os.Exit(3)
 				}
 				if policyHasVariables(*policy) {
 					return sanitizedError.New(fmt.Sprintf("Policy %v is not valid - 'apply' does not support policies with variables", policy.Name))
@@ -241,7 +243,7 @@ func getResource(path string) ([]*unstructured.Unstructured, error) {
 }
 
 func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured) error {
-
+	responseError := false
 	fmt.Printf("\n\nApplying Policy %s on Resource %s/%s/%s\n", policy.Name, resource.GetNamespace(), resource.GetKind(), resource.GetName())
 
 	mutateResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
@@ -252,6 +254,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
 			fmt.Printf("\n%d. %s", i+1, r.Message)
 		}
 		fmt.Printf("\n\n")
+		responseError = true
 	} else {
 		if len(mutateResponse.PolicyResponse.Rules) > 0 {
 			fmt.Printf("\n\nMutation:")
@@ -274,6 +277,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
 			fmt.Printf("\n%d. %s", i+1, r.Message)
 		}
 		fmt.Printf("\n\n")
+		responseError = true
 	} else {
 		if len(validateResponse.PolicyResponse.Rules) > 0 {
 			fmt.Printf("\n\nValidation:")
@@ -302,9 +306,13 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
 				fmt.Printf("\n%d. %s", i+1, r.Message)
 			}
 			fmt.Printf("\n\n")
+			responseError = true
 		}
 	}
 
+	if responseError == true{
+		os.Exit(1)
+	}
 	return nil
 }
 
diff --git a/pkg/kyverno/common/common.go b/pkg/kyverno/common/common.go
index 4744f51d3e..050bca3ea0 100644
--- a/pkg/kyverno/common/common.go
+++ b/pkg/kyverno/common/common.go
@@ -57,7 +57,8 @@ func GetPolicies(paths []string) (policies []*v1.ClusterPolicy, error error) {
 			}
 
 			if errString != "" {
-				return nil, sanitizedError.New(("falied to extract policies"))
+				fmt.Println("falied to extract policies")
+				os.Exit(2)
 			}
 
 			policies = append(policies, getPolicies...)
diff --git a/pkg/kyverno/validate/command.go b/pkg/kyverno/validate/command.go
index a5ff93c937..a1b6f6eeaf 100644
--- a/pkg/kyverno/validate/command.go
+++ b/pkg/kyverno/validate/command.go
@@ -2,6 +2,7 @@ package validate
 
 import (
 	"fmt"
+	"os"
 
 	"github.com/nirmata/kyverno/pkg/utils"
 
@@ -34,15 +35,20 @@ func Command() *cobra.Command {
 				return err
 			}
 
+			invalidPolicyFound := false
 			for _, policy := range policies {
 				err = policyvalidate.Validate(utils.MarshalPolicy(*policy), nil, true, openAPIController)
 				if err != nil {
 					fmt.Println("Policy " + policy.Name + " is invalid")
+					invalidPolicyFound = true
 				} else {
 					fmt.Println("Policy " + policy.Name + " is valid")
 				}
 			}
 
+			if invalidPolicyFound == true {
+				os.Exit(1)
+			}
 			return nil
 		},
 	}