Merging the repositories of openwhisk-cli and historic go-whisk-cli.
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..d4c2d15
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,13 @@
+clone_folder: c:\gopath\src\github.com\openwhisk\openwhisk-cli
+
+environment:
+  GOPATH: c:\gopath
+
+build: false
+
+install:
+  - echo %PATH%
+  - echo %GOPATH%
+  - set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
+  - go version
+  - go env
\ No newline at end of file
diff --git a/.idea/libraries/GOPATH__openwhisk_cli_.xml b/.idea/libraries/GOPATH__openwhisk_cli_.xml
new file mode 100644
index 0000000..a0e31a5
--- /dev/null
+++ b/.idea/libraries/GOPATH__openwhisk_cli_.xml
@@ -0,0 +1,18 @@
+<component name="libraryTable">
+  <library name="GOPATH &lt;openwhisk-cli&gt;">
+    <CLASSES>
+      <root url="file://$USER_HOME$/go/src/gopkg.in" />
+      <root url="file://$USER_HOME$/go/src/github.com" />
+      <root url="file://$USER_HOME$/go/src/golang.org" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="file://$USER_HOME$/go/src/gopkg.in" />
+      <root url="file://$USER_HOME$/go/src/github.com" />
+      <root url="file://$USER_HOME$/go/src/golang.org" />
+    </SOURCES>
+    <excluded>
+      <root url="file://$PROJECT_DIR$" />
+    </excluded>
+  </library>
+</component>
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..d32d55d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,73 @@
+# A Travis CI configuration file.
+
+language: go
+
+matrix:
+    include:
+        - os: linux
+          sudo: required
+          go: 1.7
+          env:
+            secure: 0c6mnduuUXScXl4MWyrT1oAk22SqAGzc+7KNuWUtk6berX189UzVvVY919HS/it/gHgMCMWlixoChzh9k2qYeCeDgTwR1rYWuA1Q/ACNL07vCtCwOMTihdVrOz53dy5l82AJC86cfH8Zr0cpNOyRCbCoSozmJ4GQ0lWG5lbSUD1BbNnENjP6IYAxIOfDid75UZU0iA/ebI27xImATYSrIlK1zImtKH/YYeqbsGq8jP0p9A8mg8ey0ECin+Z26AXiy9UTSvj3ujgxaS0nPwEmXu5FcA6Ad0Pr78TGvBcnv92s+MHBQfnPUuQjibrRPAquxsGN9GCWZ58gWPq4+Fg67B63dR1wtSmNEIIbXkLVuZnb2zuhh8KEHuUDVTZLjgzpVcR0J2NtDGsC09HDb88SHrGV+eFejrUVny8g/nPmvmMofX2IAhDuam7rEGVOUdY3lLDC00uZprDjZdXUBto83VmOG5OGPQ7Xe5tz4Ek+s2y3iTq9qW+BrwLO55SFYe+BTDdfSY1HiPVfc+bRbScPiOYXr+080g9zFulCePlZPrWrBCtALiPE69etGrj5FooY9+gQidpfKJ03Qy8vG4l8wl4kHjnGzFwkbnuAHoEzjMaImvjl5nAC/24z9bVUau3AMKmqZ9XrTjSpGgo10MVZwSnA+kWj7wYLKaQcCWceLrU=
+          services: docker
+        - os: osx
+          go: 1.7
+
+git:
+  depth: 3
+
+install:
+  - export DEPLOY_BUILD_READY=false
+  - go get -u github.com/golang/lint/golint
+  - go get -u github.com/stretchr/testify
+  - go get -u github.com/spf13/viper
+
+script:
+  - make lint
+  - make build
+  - make test
+  - export PATH=$PATH:$TRAVIS_BUILD_DIR;
+  - make native_test;
+  - if [ "$TRAVIS_OS_NAME" == "linux" ] ; then
+      export OPENWHISK_HOME="$(dirname "$TRAVIS_BUILD_DIR")/openwhisk";
+      ./tools/travis/install_openwhisk.sh;
+      make integration_test;
+    fi
+
+after_script:
+  - make clean
+
+after_success:
+  - DEPLOY_BUILD_READY=true
+  # This tag is automatically generated for the latest merged commit in master branch.
+  - if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_EVENT_TYPE" == "push" ] && [ "$TRAVIS_OS_NAME" == "linux" ] ; then
+      git config --global user.email "builds@travis-ci.com";
+      git config --global user.name "Travis CI";
+      export GIT_TAG="latest";
+      git tag -d $GIT_TAG;
+      git tag $GIT_TAG -a -m "Generated tag from Travis CI build $TRAVIS_BUILD_NUMBER";
+      git push -f -q https://$API_TOKEN@github.com/openwhisk/openwhisk-cli $GIT_TAG;
+    fi
+
+before_deploy:
+  - go get github.com/inconshreveable/mousetrap
+  - go get github.com/mattn/go-isatty
+  - export build_file_name=wsk
+  - export zip_file_name=OpenWhisk_CLI
+  - chmod +x tools/travis/build_tag_releases.sh
+  - ./tools/travis/build_tag_releases.sh $build_file_name $zip_file_name
+  - export RELEASE_PKG_FILE=$(ls $zip_file_name-*.zip)
+  - echo "Deploying $RELEASE_PKG_FILE to GitHub releases."
+
+deploy:
+  provider: releases
+  api_key:
+    secure: Yh1aYiM/qIWkPMSVjGUq1g9TjpACjavQ00QAqp4oqghNZc6xBcmdzsfD2VjzVPHleNI1FIZyjJ1x6laRfWBzRkAcJcjUHXA2bO/V0jqePVmgVm75WwTZ/9EaWIJeAg5CQMm5DGS28Yhc60C0ut3ZzKMWGTiKb73UADXPTGd/tjndxjfksX/THXPuInKB9QZesmluBAC2am/x/6J311WA2wqe0p1+9JFwMr8XwIcwzCwgi/d9CFpS1RnVpLE/ORSgmN/dFbZ7A/qVbx377QoxKiEB0jmUwi13f7REFAw18JdgzbQCH3X4HNu9pCJwHEAq3lP2CfmHbAXcViBeji/Xh9PPJVV9TYqO+uT8oPxCPJND1A/3O2xJ8LyZ/FP2bWqG/Ds/8SZCvxfOR/X77opUeZ4qAp7HJMVCsFi3TsnmzxCe0BOxCppVJLhoSZ2rOAPJi9mKgS/Z/VA5VhNNmnPtkReEWK4vT9h3/iCwv9anvC0RKeLckSHpCm5C5otNXtV4L990fL5L5krMatxynHnCmmhYeLg/Ns+5ncax58Y8hmhnhzTqbPGHpe79bJRfvwRI9lboq7kEj4x5O/M16TKRfQ8ZU5UHvrCPdlTfT7NUXRGZkvWX20X6Ta/DRROTF+xZGiq7da3Oi+xyNDx/LmymfR49thjzgIPXVZolknGYQ9Q=
+  file_glob: true
+  file: ${zip_file_name}-*.zip
+  overwrite: true
+  skip_cleanup: true
+  on:
+    repo: openwhisk/openwhisk-cli
+    tags: true
+    condition: "$DEPLOY_BUILD_READY = true"
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..17a2556
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,27 @@
+FROM golang:1.7
+
+# Install zip
+RUN apt-get -y update && \
+    apt-get -y install zip
+
+ENV GOPATH=/
+
+# Download and install tools
+RUN echo "Installing the godep tool"
+RUN go get github.com/tools/godep
+
+ADD . /src/github.com/openwhisk/openwhisk-cli
+
+# Load all of the dependencies from the previously generated/saved godep generated godeps.json file
+RUN echo "Restoring Go dependencies"
+RUN cd /src/github.com/openwhisk/openwhisk-cli && /bin/godep restore -v
+
+# wsk binary will be placed under a build folder
+RUN mkdir /src/github.com/openwhisk/openwhisk-cli/build
+
+ARG CLI_OS
+ARG CLI_ARCH
+
+# Build the Go wsk CLI binaries and compress resultant binaries
+RUN chmod +x /src/github.com/openwhisk/openwhisk-cli/build.sh
+RUN cd /src/github.com/openwhisk/openwhisk-cli && ./build.sh
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 7a72290..9c0fd26 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,15 +1,20 @@
 {
-	"ImportPath": "github.ibm.com/BlueMix-Fabric/go-whisk-cli",
-	"GoVersion": "go1.5",
+	"ImportPath": "github.com/openwhisk/openwhisk-cli",
+	"GoVersion": "go1.",
+	"GodepVersion": "v74",
 	"Deps": [
 		{
+			"ImportPath": "github.com/cloudfoundry/jibber_jabber",
+			"Rev": "bcc4c8345a21301bf47c032ff42dd1aae2fe3027"
+		},
+		{
 			"ImportPath": "github.com/fatih/color",
-			"Comment": "v0.1-14-g7a5857d",
-			"Rev": "7a5857db0b2752a436d8461d88c42dea0ee191c0"
+			"Comment": "v0.1-19-g87d4004",
+			"Rev": "87d4004f2ab62d0d255e0a38f1680aa534549fe3"
 		},
 		{
 			"ImportPath": "github.com/google/go-querystring/query",
-			"Rev": "2a60fc2ba6c19de80291203597d752e9ba58e4c0"
+			"Rev": "9235644dd9e52eeae6fa48efd539fdc351a0af53"
 		},
 		{
 			"ImportPath": "github.com/hokaccha/go-prettyjson",
@@ -21,31 +26,60 @@
 		},
 		{
 			"ImportPath": "github.com/mattn/go-colorable",
-			"Rev": "9fdad7c47650b7d2e1da50644c1f4ba7f172f252"
+			"Comment": "v0.0.6-9-gd228849",
+			"Rev": "d228849504861217f796da67fae4f6e347643f15"
 		},
 		{
 			"ImportPath": "github.com/mattn/go-isatty",
-			"Rev": "56b76bdf51f7708750eac80fa38b952bb9f32639"
+			"Rev": "66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8"
 		},
 		{
 			"ImportPath": "github.com/mitchellh/go-homedir",
-			"Rev": "d682a8f0cf139663a984ff12528da460ca963de9"
+			"Rev": "1111e456ffea841564ac0fa5f69c26ef44dafec9"
+		},
+		{
+			"ImportPath": "github.com/nicksnyder/go-i18n/i18n",
+			"Comment": "v1.4.0",
+			"Rev": "37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3"
+		},
+		{
+			"ImportPath": "github.com/nicksnyder/go-i18n/i18n/bundle",
+			"Comment": "v1.4.0",
+			"Rev": "37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3"
+		},
+		{
+			"ImportPath": "github.com/nicksnyder/go-i18n/i18n/language",
+			"Comment": "v1.4.0",
+			"Rev": "37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3"
+		},
+		{
+			"ImportPath": "github.com/nicksnyder/go-i18n/i18n/translation",
+			"Comment": "v1.4.0",
+			"Rev": "37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3"
 		},
 		{
 			"ImportPath": "github.com/spf13/cobra",
-			"Rev": "65a708cee0a4424f4e353d031ce440643e312f92"
+			"Rev": "1238ba19d24b0b9ceee2094e1cb31947d45c3e86"
 		},
 		{
 			"ImportPath": "github.com/spf13/pflag",
-			"Rev": "7f60f83a2c81bc3c3c0d5297f61ddfa68da9d3b7"
-		},
-		{
-			"ImportPath": "github.ibm.com/BlueMix-Fabric/go-whisk/whisk",
-			"Rev": "f6fd6fbaeb0a99ec76f84f7a867d236a5a0309ad"
+			"Rev": "367864438f1b1a3c7db4da06a2f55b144e6784e0"
 		},
 		{
 			"ImportPath": "golang.org/x/sys/unix",
-			"Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e"
-		}
+			"Rev": "7f918dd405547ecb864d14a8ecbbfe205b5f930f"
+		},
+		{
+			"ImportPath": "gopkg.in/yaml.v2",
+			"Rev": "e4d366fc3c7938e2958e662b4258c7a89e1f0e3e"
+		},
+		{
+			"ImportPath": "github.com/openwhisk/openwhisk-client-go/whisk",
+			"Rev": "5c216065673c15e35e0baa8feca9b986a6b73517"
+		},
+        {
+            "ImportPath": "github.com/openwhisk/openwhisk-client-go/wski18n",
+            "Rev": "5c216065673c15e35e0baa8feca9b986a6b73517"
+        }
 	]
 }
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4b5f304
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+SOURCEDIR=.
+
+SOURCES := $(shell find $(SOURCEDIR) -name '*.go')
+BINARY=wsk
+
+VERSION=1.0.0
+
+BUILD=`git rev-parse HEAD`
+
+deps:
+	@echo "Installing dependencies"
+	go get -d -t ./...
+
+LDFLAGS=-ldflags "-X main.Version=`date -u '+%Y-%m-%dT%H:%M:%S'` -X main.Build=`git rev-parse HEAD` "
+
+updatedeps:
+	@echo "Updating all dependencies"
+	@go get -d -u -f -fix -t ./...
+
+# Build the project
+build: deps
+	go build ${LDFLAGS} -o ${BINARY}
+
+test:
+	@echo "Launch the unit tests."
+	go test ./... -tags=unit
+
+native_test:
+	@echo "Launch the native tests for the commands."
+	go test -v ./... -tags=native
+
+# Run the integration test against OpenWhisk
+integration_test:
+	@echo "Launch the integration tests."
+	go test -v ./... -tags=integration
+
+format:
+	@echo "Formatting"
+	go fmt ./...
+
+lint: format
+	@echo "Linting"
+	golint .
+
+install:
+	go install
+
+# Cleans our project: deletes binaries
+clean:
+	if [ -f ${BINARY} ] ; then rm ${BINARY}; fi
+
+.PHONY: clean install
\ No newline at end of file
diff --git a/README.md b/README.md
index 7aaaaf4..ec41e8c 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,83 @@
-# Whisk Command Line App
+# OpenWhisk Command Line Interface `wsk`
 
-`$ git clone git@github.ibm.com:BlueMix-Fabric/go-whisk.git $GOPATH/src/github.ibm.com/BlueMix-Fabric/go-whisk`
+The OpenWhisk Command Line Interface (OpenWhisk CLI) is a unified tool that provides a consistent interface to
+interact with OpenWhisk services. With this tool to download and configure, you are able to manage OpenWhisk services
+from the command line and automate them through scripts.
 
-`$ git clone git@github.ibm.com:BlueMix-Fabric/go-whisk-cli.git $GOPATH/src/github.ibm.com/BlueMix-Fabric/go-whisk-cli`
 
-`$ cd $GOPATH/src/github.ibm.com/BlueMix-Fabric/go-whisk-cli`
+# Where to download the binary of OpenWhisk CLI
 
-`$ go build -o wsk main.go`
+The OpenWhisk CLI is available on the release page: [click here to download](https://github.com/openwhisk/openwhisk-cli/releases).
+We currently have binaries available for Linux, Mac OS and windows under amd64 architecture. You can download the
+binary, which fits your local environment.
 
-`$ ./wsk -h`
 
----
+# How to build the binary locally
 
-[Whisk Command Line Tutorial](https://github.rtp.raleigh.ibm.com/whisk-development/whisk/blob/master/blue/docs/tutorial/WhiskCliTutorial.md)
+You can also choose to build the binary locally based on the source code. First, install the prerequisites to 
+download and build OpenWhisk CLI: [installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
+
+Then, download the source code via the Git command:
+
+```
+$ git clone https://github.com/openwhisk/openwhisk-cli.git
+```
+
+OpenWhisk CLI(`wsk`) is produced in a Docker container during the build process which is copied from the
+Docker container to the local file system in the following directory: bin. This binary will be platform
+specific, it will only run on the operating system, and CPU architecture that matches the build machine.
+
+## Build the binary with Go
+
+The binary can be built by Go build command. Make sure that you have Go installed: [installing Go](https://golang.org/doc/install).
+
+After that, open an terminal, go to the directory of OpenWhisk CLI home directory, and build the binary via
+the following command:
+
+```
+$ go build -o wsk
+```
+
+If you would like to build the binary for a specific operating system, you may add the arguments GOOS and
+GOARCH into the Go build command. Since it is only applicable under amd64 architecture, you have to set GOARCH
+to amd64. GOOS can be set to "linux" "darwin" or "windows".
+
+For example, run the following command to build the binary for Linux:
+
+```
+$ GOOS=linux GOARCH=amd64 go build -o wsk
+```
+
+If it is executed successfully, you can find your binary `wsk` directly under OpenWhisk CLI home directory.
+
+## Build the binary with Docker and Gradle
+
+This is the second choice for you to build the binary. Make sure that you have Docker and gradle on your machine:
+[installing Docker](https://docs.docker.com/engine/installation/) and [installing Gradle](https://gradle.org/install) for your local machine.
+
+After that, open an terminal, go to the directory of OpenWhisk CLI home directory, and
+build the binary via the following command under Linux or Mac:
+
+```
+$ ./gradlew distDocker
+```
+
+or run the following command for Windows:
+
+```
+$ ./gradlew.bat distDocker
+```
+
+Finally, you can find the binary `wsk` or `wsk.exe` in the bin folder under the OpenWhisk CLI home directory.
+
+
+# How to use the binary
+
+When you have the binary, you can copy the binary to any folder, and add folder into the system PATH in order to
+run the OpenWhisk CLI command. To get the CLI command help, execute the following command:
+
+```
+$ wsk --help
+```
+
+To get CLI command debug information, include the -d, or --debug flag when executing this command.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..4204c1a
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,93 @@
+ext.dockerImageName = "cli"
+ext.dockerContainerName = "cli"
+ext.dockerBuildArgs = getDockerBuildArgs()
+apply from: 'gradle/docker.gradle'
+
+
+task removeBinary(type: Delete) {
+    delete "${projectDir}/bin/wsk"
+    delete "${projectDir}/bin/mac"
+    delete "${projectDir}/bin/linux"
+    delete "${projectDir}/bin/windows"
+}
+
+task distBinary(dependsOn: [removeBinary, distDocker]) {
+    doLast {
+        run(dockerBinary + ["rm", "-f", dockerContainerName], true)
+        run(dockerBinary + ["run", "--name", dockerContainerName, dockerTaggedImageName])
+
+        // Copy all Go binaries from Docker into openwhisk/bin folder
+        run(dockerBinary + ["cp", dockerContainerName +
+                ":/src/github.com/openwhisk/openwhisk-cli/build/.", "${projectDir}/bin"])
+
+        run(dockerBinary + ["rm", "-f", dockerContainerName])
+    }
+}
+
+task dumpOSInfo {
+    doLast {
+        println "os.name = "+getOsName()
+        println "os.arch = "+getOsArch()
+        println "go.name = "+mapOsNameToGoName(getOsName())
+        println "go.arch = "+mapOsArchToGoArch(getOsArch())
+    }
+}
+
+task copyCLIShortcut(type: Copy, dependsOn: [distBinary, dumpOSInfo]) {
+    String go_osname     = mapOsNameToGoName(getOsName())
+    String go_osarch     = mapOsArchToGoArch(getOsArch())
+    String from_path_wsk = "${projectDir}/bin/${go_osname}/${go_osarch}/wsk"
+    String to_path_dir   = "${projectDir}/bin"
+
+    from from_path_wsk
+    into to_path_dir
+}
+
+pushImage.finalizedBy copyCLIShortcut
+
+// Returns the Go CLI docker build args
+def getDockerBuildArgs() {
+    String local_os = mapOsNameToGoName(getOsName())
+    String local_arch = mapOsArchToGoArch(getOsArch())
+    def res = []
+
+    if(!project.hasProperty('crossCompileCLI') || project.crossCompileCLI == "false") {
+        res = ["CLI_OS=${local_os}", "CLI_ARCH=${local_arch}"]
+    } else {
+        res = ["CLI_OS=mac linux windows", "CLI_ARCH=386 amd64"]
+    }
+
+    return res
+}
+
+def run(cmd, ignoreError = false) {
+    println("Executing '${cmd.join(" ")}'")
+    def proc = cmd.execute()
+    proc.waitFor()
+    if(!ignoreError && proc.exitValue() != 0) {
+        println("Command '${cmd.join(" ")}' failed with exitCode ${proc.exitValue()}")
+    }
+}
+
+def getOsName() {
+    return System.properties['os.name']
+}
+
+def getOsArch() {
+    return System.properties['os.arch']
+}
+
+def mapOsNameToGoName(String osname) {
+    String osname_l = osname.toLowerCase()
+    if (osname_l.contains("nux") || osname.contains("nix")) return "linux"
+    if (osname_l.contains("mac")) return "mac"
+    if (osname_l.contains("windows")) return "windows"
+    return osname_l
+}
+
+def mapOsArchToGoArch(String osarch) {
+    String osarch_l = osarch.toLowerCase()
+    if (osarch_l.contains("x86_64") || osarch_l == "amd64") return "amd64"
+    if (osarch_l.contains("i386") || osarch_l.contains("x86_32")) return "386"
+    return osarch_l
+}
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..4a7fca8
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+
+set +x
+set -e
+
+get_bin_name () {
+  local os=$1
+  local bin="wsk"
+
+  if [ $os = "windows" ]; then
+    bin="${bin}.exe";
+  fi
+
+  echo $bin;
+};
+
+build_cli () {
+  local os=$1
+  local arch=$2
+  local bin=$3
+
+  echo "Building for OS '$os' and architecture '$arch'"
+
+  if [ $os = "mac" ]; then
+    export GOOS=darwin;
+  else
+    export GOOS=$os;
+  fi
+
+  export GOARCH=$arch
+
+  cd /src/github.com/openwhisk/openwhisk-cli
+  go build -ldflags "-X main.CLI_BUILD_TIME=`date -u '+%Y-%m-%dT%H:%M:%S%:z'`" -v -o build/$os/$arch/$bin main.go;
+};
+
+get_compressed_name() {
+  local os=$1
+  local arch=$2
+  local product_name="OpenWhisk_CLI"
+
+  if [ $arch = amd64 ]; then
+      comp_name="$product_name-$os";
+  elif [ $arch = 386 ]; then
+      comp_name="$product_name-$os-32bit";
+  else
+      comp_name="$product_name-$os-$arch";
+  fi
+
+  echo $comp_name;
+};
+
+compress_binary() {
+    local comp_name=$1
+    local bin=$2
+    local os=$3
+    local arch=$4
+
+    cd build/$os/$arch
+
+    if [ $os = "linux" ]; then
+      comp_name="$comp_name.tgz"
+      tar -cvzf $comp_name $bin >/dev/null 2>&1;
+    else
+      comp_name="$comp_name.zip"
+      zip $comp_name $bin >/dev/null 2>&1;
+    fi
+
+    cd ../../..
+    echo $os/$arch/$comp_name;
+};
+
+create_cli_packages() {
+  local dirIndex="{\"cli\":{"
+
+  for platform in $platforms; do
+    dirIndex="$dirIndex\"$platform\":{"
+
+    for arch in $archs; do
+      bin=$(get_bin_name $platform)
+      build_cli $platform $arch $bin
+      comp_name=$(get_compressed_name $platform $arch)
+      comp_path=$(compress_binary $comp_name $bin $platform $arch)
+
+      if [ $arch = $default_arch ]; then
+          dirIndex="$dirIndex\"default\":{\"path\":\"$comp_path\"},";
+      fi
+
+      dirIndex="$dirIndex\"$arch\":{\"path\":\"$comp_path\"},";
+    done
+
+    dirIndex="$(echo $dirIndex | rev | cut -c2- | rev)"
+    dirIndex="$dirIndex},";
+  done
+
+  dirIndex="$(echo $dirIndex | rev | cut -c2- | rev)"
+  dirIndex="$dirIndex}}"
+
+  echo $dirIndex > ./build/content.json
+};
+
+platforms="$CLI_OS"
+archs="$CLI_ARCH";
+default_arch="amd64"
+
+create_cli_packages
diff --git a/commands/action.go b/commands/action.go
index 61e1274..2393a51 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -1,371 +1,922 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"archive/tar"
-	"compress/gzip"
-	"encoding/base64"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strings"
+    "encoding/base64"
+    "errors"
+    "fmt"
+    "path/filepath"
+    "io"
+    "strings"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 
-	"github.com/fatih/color"
-	"github.com/spf13/cobra"
+    "github.com/fatih/color"
+    "github.com/spf13/cobra"
+    "github.com/mattn/go-colorable"
 )
 
-//////////////
-// Commands //
-//////////////
+const MEMORY_LIMIT = 256
+const TIMEOUT_LIMIT = 60000
+const LOGSIZE_LIMIT = 10
+const ACTIVATION_ID = "activationId"
+const WEB_EXPORT_ANNOT = "web-export"
+const RAW_HTTP_ANNOT = "raw-http"
+const FINAL_ANNOT = "final"
 
 var actionCmd = &cobra.Command{
-	Use:   "action",
-	Short: "work with actions",
+    Use:   "action",
+    Short: wski18n.T("work with actions"),
 }
 
 var actionCreateCmd = &cobra.Command{
-	Use:   "create <name string> <artifact string>",
-	Short: "create a new action",
+    Use:           "create ACTION_NAME ACTION",
+    Short:         wski18n.T("create a new action"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var action *whisk.Action
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		action, err := parseAction(cmd, args)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		action, _, err = client.Actions.Insert(action, false)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(
+            args,
+            2,
+            2,
+            "Action create",
+            wski18n.T("An action name and action are required.")); whiskErr != nil {
+                return whiskErr
+        }
 
-		fmt.Printf("%s created action %s", color.GreenString("ok:"), boldString(action.Name))
-	},
+        if action, err = parseAction(cmd, args, false); err != nil {
+            return actionParseError(cmd, args, err)
+        }
+
+        if _, _, err = client.Actions.Insert(action, false); err != nil {
+            return actionInsertError(action, err)
+        }
+
+        printActionCreated(action.Name)
+
+        return nil
+    },
 }
 
 var actionUpdateCmd = &cobra.Command{
-	Use:   "update <name string> <artifact string>",
-	Short: "update an existing action",
+    Use:           "update ACTION_NAME [ACTION]",
+    Short:         wski18n.T("update an existing action, or create an action if it does not exist"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var action *whisk.Action
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		action, err := parseAction(cmd, args)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		action, _, err = client.Actions.Insert(action, true)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(
+            args,
+            1,
+            2,
+            "Action update",
+            wski18n.T("An action name is required. An action is optional.")); whiskErr != nil {
+                return whiskErr
+        }
 
-		fmt.Printf("%s updated action %s", color.GreenString("ok:"), boldString(action.Name))
+        if action, err = parseAction(cmd, args, false); err != nil {
+            return actionParseError(cmd, args, err)
+        }
 
-	},
+        if _, _, err = client.Actions.Insert(action, true); err != nil {
+            return actionInsertError(action, err)
+        }
+
+        printActionUpdated(action.Name)
+
+        return nil
+    },
 }
 
 var actionInvokeCmd = &cobra.Command{
-	Use:   "invoke <name string> <payload string>",
-	Short: "invoke action",
-	Run: func(cmd *cobra.Command, args []string) {
+    Use:           "invoke ACTION_NAME",
+    Short:         wski18n.T("invoke action"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var parameters interface{}
+        var qualifiedName QualifiedName
+        var paramArgs []string
 
-		var err error
-		var actionName, payloadArg string
-		if len(args) < 1 || len(args) > 2 {
-			err = errors.New("Invalid argument list")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(
+            args,
+            1,
+            1,
+            "Action invoke",
+            wski18n.T("An action name is required.")); whiskErr != nil {
+                return whiskErr
+        }
 
-		actionName = args[0]
+        if qualifiedName, err = parseQualifiedName(args[0]); err != nil {
+            return parseQualifiedNameError(args[0], err)
+        }
 
-		payload := map[string]interface{}{}
+        client.Namespace = qualifiedName.namespace
+        paramArgs = flags.common.param
 
-		if len(flags.common.param) > 0 {
-			parameters, err := parseParameters(flags.common.param)
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
+        if len(paramArgs) > 0 {
+            if parameters, err = getJSONFromStrings(paramArgs, false); err != nil {
+                return getJSONFromStringsParamError(paramArgs, false, err)
+            }
+        }
+        if flags.action.result {flags.common.blocking = true}
 
-			for _, param := range parameters {
-				payload[param.Key] = param.Value
-			}
-		}
+        res, _, err := client.Actions.Invoke(
+            qualifiedName.entityName,
+            parameters,
+            flags.common.blocking,
+            flags.action.result)
 
-		if len(args) == 2 {
-			payloadArg = args[1]
-			reader := strings.NewReader(payloadArg)
-			err = json.NewDecoder(reader).Decode(&payload)
-			if err != nil {
-				payload["payload"] = payloadArg
-			}
-		}
+        return handleInvocationResponse(qualifiedName, parameters, res, err)
+    },
+}
 
-		activation, _, err := client.Actions.Invoke(actionName, payload, flags.common.blocking)
-		if err != nil {
-			fmt.Printf("error: %s", err)
-			return
-		}
+func handleInvocationResponse(
+    qualifiedName QualifiedName,
+    parameters interface{},
+    result map[string]interface{},
+    err error) (error) {
+        if err == nil {
+            printInvocationMsg(
+                qualifiedName.namespace,
+                qualifiedName.entityName,
+                getValueFromJSONResponse(ACTIVATION_ID, result),
+                result,
+                color.Output)
+        } else {
+            if !flags.common.blocking {
+                return handleInvocationError(err, qualifiedName.entityName, parameters)
+            } else {
+                if isBlockingTimeout(err) {
+                    printBlockingTimeoutMsg(
+                        qualifiedName.namespace,
+                        qualifiedName.entityName,
+                        getValueFromJSONResponse(ACTIVATION_ID, result))
+                } else if isApplicationError(err) {
+                    printInvocationMsg(
+                        qualifiedName.namespace,
+                        qualifiedName.entityName,
+                        getValueFromJSONResponse(ACTIVATION_ID, result),
+                        result,
+                        colorable.NewColorableStderr())
+                } else {
+                    return handleInvocationError(err, qualifiedName.entityName, parameters)
+                }
+            }
+        }
 
-		if flags.common.blocking && flags.action.result {
-			printJSON(activation.Response.Result)
-		} else if flags.common.blocking {
-			fmt.Printf("%s invoked %s with id %s\n", color.GreenString("ok:"), boldString(actionName), boldString(activation.ActivationID))
-			boldPrintf("response:\n")
-			printJSON(activation.Response)
-		} else {
-			fmt.Printf("%s invoked %s with id %s\n", color.GreenString("ok:"), boldString(actionName), boldString(activation.ActivationID))
-		}
-
-	},
+        return err
 }
 
 var actionGetCmd = &cobra.Command{
-	Use:   "get <name string>",
-	Short: "get action",
+    Use:           "get ACTION_NAME [FIELD_FILTER]",
+    Short:         wski18n.T("get action"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var field string
+        var action *whisk.Action
+        var qualifiedName QualifiedName
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 2, "Action get", wski18n.T("An action name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        if len(args) > 1 {
+            field = args[1]
 
-		actionName := args[0]
-		action, _, err := client.Actions.Get(actionName)
-		if err != nil {
-			fmt.Printf("error: %s", err)
-			return
-		}
-		// print out response
+            if !fieldExists(&whisk.Action{}, field) {
+                return invalidFieldFilterError(field)
+            }
+        }
 
-		if flags.common.summary {
-			fmt.Printf("%s /%s/%s\n", boldString("action"), action.Namespace, action.Name)
-		} else {
-			fmt.Printf("%s got action %s\n", color.GreenString("ok:"), boldString(actionName))
-			printJSON(action)
-		}
+        if qualifiedName, err = parseQualifiedName(args[0]); err != nil {
+            return parseQualifiedNameError(args[0], err)
+        }
 
-	},
+        client.Namespace = qualifiedName.namespace
+
+        if action, _, err = client.Actions.Get(qualifiedName.entityName); err != nil {
+            return actionGetError(qualifiedName.entityName, err)
+        }
+
+        if flags.common.summary {
+            printSummary(action)
+        } else {
+            if len(field) > 0 {
+                printActionGetWithField(qualifiedName.entityName, field, action)
+            } else {
+                printActionGet(qualifiedName.entityName, action)
+            }
+        }
+
+        return nil
+    },
 }
 
 var actionDeleteCmd = &cobra.Command{
-	Use:   "delete <name string>",
-	Short: "delete action",
+    Use:           "delete ACTION_NAME",
+    Short:         wski18n.T("delete action"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var qualifiedName QualifiedName
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		actionName := args[0]
-		_, err := client.Actions.Delete(actionName)
-		if err != nil {
-			fmt.Printf("error: %s", err)
-			return
-		}
-		// print out response
-		fmt.Printf("%s deleted action %s\n", color.GreenString("ok:"), boldString(actionName))
-	},
+        if whiskErr := checkArgs(
+            args,
+            1,
+            1,
+            "Action delete",
+            wski18n.T("An action name is required.")); whiskErr != nil {
+                return whiskErr
+        }
+
+        if qualifiedName, err = parseQualifiedName(args[0]); err != nil {
+            return parseQualifiedNameError(args[0], err)
+        }
+
+        client.Namespace = qualifiedName.namespace
+
+        if _, err = client.Actions.Delete(qualifiedName.entityName); err != nil {
+            return actionDeleteError(qualifiedName.entityName, err)
+        }
+
+        printActionDeleted(qualifiedName.entityName)
+
+        return nil
+    },
 }
 
 var actionListCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list all actions",
+    Use:           "list [NAMESPACE]",
+    Short:         wski18n.T("list all actions"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var qualifiedName QualifiedName
+        var actions []whisk.Action
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		qName := qualifiedName{}
-		if len(args) == 1 {
-			qName, err = parseQualifiedName(args[0])
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
-			ns := qName.namespace
-			if len(ns) == 0 {
-				err = errors.New("No valid namespace detected.  Make sure that namespace argument is preceded by a \"/\"")
-				fmt.Printf("error: %s\n", err)
-				return
-			}
+        if len(args) == 1 {
+            if qualifiedName, err = parseQualifiedName(args[0]); err != nil {
+                return parseQualifiedNameError(args[0], err)
+            }
 
-			client.Namespace = ns
+            client.Namespace = qualifiedName.namespace
+        } else if whiskErr := checkArgs(
+            args,
+            0,
+            1,
+            "Action list",
+            wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-			if pkg := qName.packageName; len(pkg) > 0 {
-				// todo :: scope call to package
-			}
-		}
+        options := &whisk.ActionListOptions{
+            Skip:  flags.common.skip,
+            Limit: flags.common.limit,
+        }
 
-		options := &whisk.ActionListOptions{
-			Skip:  flags.common.skip,
-			Limit: flags.common.limit,
-		}
+        if actions, _, err = client.Actions.List(qualifiedName.entityName, options); err != nil {
+            return actionListError(qualifiedName.entityName, options, err)
+        }
 
-		actions, _, err := client.Actions.List(options)
-		if err != nil {
-			fmt.Printf("error: %s", err)
-			return
-		}
-		printList(actions)
-	},
+        printList(actions)
+
+        return nil
+    },
 }
 
-func parseAction(cmd *cobra.Command, args []string) (*whisk.Action, error) {
-	var err error
-	var actionName, artifact string
-	if len(args) < 1 || len(args) > 2 {
-		err = errors.New("Invalid argument list")
-		return nil, err
-	}
+func parseAction(cmd *cobra.Command, args []string, update bool) (*whisk.Action, error) {
+    var err error
+    var artifact string
+    var existingAction *whisk.Action
+    var paramArgs []string
+    var annotArgs []string
+    var parameters interface{}
+    var annotations interface{}
 
-	actionName = args[0]
+    qualifiedName := QualifiedName{}
 
-	if len(args) == 2 {
-		artifact = args[1]
-	}
+    if qualifiedName, err = parseQualifiedName(args[0]); err != nil {
+        return nil, parseQualifiedNameError(args[0], err)
+    }
 
-	exec := whisk.Exec{}
+    if len(args) == 2 {
+        artifact = args[1]
+    }
 
-	parameters, err := parseParameters(flags.common.param)
-	if err != nil {
-		return nil, err
-	}
+    client.Namespace = qualifiedName.namespace
+    action := new(whisk.Action)
+    action.Name = qualifiedName.entityName
+    action.Namespace = qualifiedName.namespace
+    action.Limits = getLimits(
+        cmd.LocalFlags().Changed(MEMORY_FLAG),
+        cmd.LocalFlags().Changed(LOG_SIZE_FLAG),
+        cmd.LocalFlags().Changed(TIMEOUT_FLAG),
+        flags.action.memory,
+        flags.action.logsize,
+        flags.action.timeout)
 
-	annotations, err := parseAnnotations(flags.common.annotation)
-	if err != nil {
-		return nil, err
-	}
+    paramArgs = flags.common.param
+    annotArgs = flags.common.annotation
 
-	limits := whisk.Limits{
-		Timeout: flags.action.timeout,
-		Memory:  flags.action.memory,
-	}
+    if len(paramArgs) > 0 {
+        if parameters, err = getJSONFromStrings(paramArgs, true); err != nil {
+            return nil, getJSONFromStringsParamError(paramArgs, true, err)
+        }
 
-	if flags.action.docker {
-		exec.Image = artifact
-	} else if flags.action.copy {
-		existingAction, _, err := client.Actions.Get(actionName)
-		if err != nil {
-			return nil, err
-		}
-		exec = existingAction.Exec
-	} else if flags.action.sequence {
-		currentNamespace := client.Config.Namespace
-		client.Config.Namespace = "whisk.system"
-		pipeAction, _, err := client.Actions.Get("system/pipe")
-		if err != nil {
-			return nil, err
-		}
-		exec = pipeAction.Exec
-		client.Config.Namespace = currentNamespace
-	} else if artifact != "" {
-		stat, err := os.Stat(artifact)
-		if err != nil {
-			// file does not exist
-			return nil, err
-		}
+        action.Parameters = parameters.(whisk.KeyValueArr)
+    }
 
-		file, err := ioutil.ReadFile(artifact)
-		if err != nil {
-			return nil, err
-		}
+    if len(annotArgs) > 0 {
+        if annotations, err = getJSONFromStrings(annotArgs, true); err != nil {
+            return nil, getJSONFromStringsAnnotError(annotArgs, true, err)
+        }
 
-		exec.Code = string(file)
+        action.Annotations = annotations.(whisk.KeyValueArr)
+    }
 
-		if matched, _ := regexp.MatchString(".swift$", stat.Name()); matched {
-			exec.Kind = "swift"
-		} else {
-			exec.Kind = "nodejs"
-		}
-	}
+    if flags.action.copy {
+        copiedQualifiedName := QualifiedName{}
 
-	if flags.action.lib != "" {
-		file, err := os.Open(flags.action.lib)
-		if err != nil {
-			return nil, err
-		}
+        if copiedQualifiedName, err = parseQualifiedName(args[1]); err != nil {
+            return nil, parseQualifiedNameError(args[1], err)
+        }
 
-		var r io.Reader
-		switch ext := filepath.Ext(file.Name()); ext {
-		case "tar":
-			r = tar.NewReader(file)
-		case "gzip":
-			r, err = gzip.NewReader(file)
-		default:
-			err = fmt.Errorf("Unrecognized file compression %s", ext)
-		}
-		if err != nil {
-			return nil, err
-		}
-		lib, err := ioutil.ReadAll(r)
-		if err != nil {
-			return nil, err
-		}
+        client.Namespace = copiedQualifiedName.namespace
 
-		exec.Init = base64.StdEncoding.EncodeToString(lib)
-	}
+        if existingAction, _, err = client.Actions.Get(copiedQualifiedName.entityName); err != nil {
+            return nil, actionGetError(copiedQualifiedName.entityName, err)
+        }
 
-	action := &whisk.Action{
-		Name:        actionName,
-		Publish:     flags.action.shared,
-		Exec:        exec,
-		Annotations: annotations,
-		Parameters:  parameters,
-		Limits:      limits,
-	}
+        client.Namespace = qualifiedName.namespace
+        action.Exec = existingAction.Exec
+        action.Parameters = append(action.Parameters, existingAction.Parameters...)
+        action.Annotations = append(action.Annotations, existingAction.Annotations...)
+    } else if flags.action.sequence {
+        action.Exec = new(whisk.Exec)
+        action.Exec.Kind = "sequence"
+        action.Exec.Components = csvToQualifiedActions(artifact)
+    } else if len(artifact) > 0 {
+        action.Exec, err = getExec(args[1], flags.action.kind, flags.action.docker, flags.action.main)
+    }
 
-	return action, nil
+    if cmd.LocalFlags().Changed(WEB_FLAG) {
+        action.Annotations, err = webAction(flags.action.web, action.Annotations, qualifiedName.entityName, update)
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Parsed action struct: %#v\n", action)
+
+    return action, err
 }
 
-///////////
-// Flags //
-///////////
+func getExec(artifact string, kind string, isDocker bool, mainEntry string) (*whisk.Exec, error) {
+    var err error
+    var code string
+    var exec *whisk.Exec
+
+    ext := filepath.Ext(artifact)
+    exec = new(whisk.Exec)
+
+    if !isDocker || ext == ".zip" {
+        code, err = readFile(artifact)
+
+        if ext == ".zip" || ext == ".jar" {
+            // Base64 encode the file
+            code = base64.StdEncoding.EncodeToString([]byte(code))
+            exec.Code = &code
+        } else {
+            exec.Code = &code
+        }
+
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", artifact, err)
+            return nil, err
+        }
+    }
+
+    if len(kind) > 0 {
+        exec.Kind = kind
+    } else if isDocker {
+        exec.Kind = "blackbox"
+        if ext != ".zip" {
+            exec.Image = artifact
+        } else {
+            exec.Image = "openwhisk/dockerskeleton"
+        }
+    } else if ext == ".swift" {
+        exec.Kind = "swift:default"
+    } else if ext == ".js" {
+        exec.Kind = "nodejs:default"
+    } else if ext == ".py" {
+        exec.Kind = "python:default"
+    } else if ext == ".jar" {
+        exec.Kind = "java:default"
+    } else {
+        if ext == ".zip" {
+            return nil, zipKindError()
+        } else {
+            return nil, extensionError(ext)
+        }
+    }
+
+    // Error if entry point is not specified for Java
+    if len(mainEntry) != 0 {
+        exec.Main = mainEntry
+    } else {
+        if exec.Kind == "java" {
+            return nil, javaEntryError()
+        }
+    }
+
+    return exec, nil
+}
+
+func webAction(webMode string, annotations whisk.KeyValueArr, entityName string, fetch bool) (whisk.KeyValueArr, error){
+    switch strings.ToLower(webMode) {
+    case "yes":
+        fallthrough
+    case "true":
+        return webActionAnnotations(fetch, annotations, entityName, addWebAnnotations)
+    case "no":
+        fallthrough
+    case "false":
+        return webActionAnnotations(fetch, annotations, entityName, deleteWebAnnotations)
+    case "raw":
+        return webActionAnnotations(fetch, annotations, entityName, addRawAnnotations)
+    default:
+        return nil, webInputError(webMode)
+    }
+}
+
+type WebActionAnnotationMethod func(annotations whisk.KeyValueArr) (whisk.KeyValueArr)
+
+func webActionAnnotations(
+    fetchAnnotations bool,
+    annotations whisk.KeyValueArr,
+    entityName string,
+    webActionAnnotationMethod WebActionAnnotationMethod) (whisk.KeyValueArr, error) {
+        var action *whisk.Action
+        var err error
+
+        if annotations != nil || !fetchAnnotations {
+            annotations = webActionAnnotationMethod(annotations)
+        } else {
+            if action, _, err = client.Actions.Get(entityName); err != nil {
+                return nil, actionGetError(entityName, err)
+            } else {
+                annotations = webActionAnnotationMethod(action.Annotations)
+            }
+        }
+
+        return annotations, nil
+}
+
+func addWebAnnotations(annotations whisk.KeyValueArr) (whisk.KeyValueArr) {
+    annotations = deleteWebAnnotationKeys(annotations)
+    annotations = addKeyValue(WEB_EXPORT_ANNOT, true, annotations)
+    annotations = addKeyValue(RAW_HTTP_ANNOT, false, annotations)
+    annotations = addKeyValue(FINAL_ANNOT, true, annotations)
+
+    return annotations
+}
+
+func deleteWebAnnotations(annotations whisk.KeyValueArr) (whisk.KeyValueArr) {
+    annotations = deleteWebAnnotationKeys(annotations)
+    annotations = addKeyValue(WEB_EXPORT_ANNOT, false, annotations)
+    annotations = addKeyValue(RAW_HTTP_ANNOT, false, annotations)
+    annotations = addKeyValue(FINAL_ANNOT, false, annotations)
+
+    return annotations
+}
+
+func addRawAnnotations(annotations whisk.KeyValueArr) (whisk.KeyValueArr) {
+    annotations = deleteWebAnnotationKeys(annotations)
+    annotations = addKeyValue(WEB_EXPORT_ANNOT, true, annotations)
+    annotations = addKeyValue(RAW_HTTP_ANNOT, true, annotations)
+    annotations = addKeyValue(FINAL_ANNOT, true, annotations)
+
+    return annotations
+}
+
+func deleteWebAnnotationKeys(annotations whisk.KeyValueArr) (whisk.KeyValueArr) {
+    annotations = deleteKey(WEB_EXPORT_ANNOT, annotations)
+    annotations = deleteKey(RAW_HTTP_ANNOT, annotations)
+    annotations = deleteKey(FINAL_ANNOT, annotations)
+
+    return annotations
+}
+
+func getLimits(memorySet bool, logSizeSet bool, timeoutSet bool, memory int, logSize int, timeout int) (*whisk.Limits) {
+    var limits *whisk.Limits
+
+    if memorySet || logSizeSet || timeoutSet {
+        limits = new(whisk.Limits)
+
+        if memorySet {
+            limits.Memory = &memory
+        }
+
+        if logSizeSet {
+            limits.Logsize = &logSize
+        }
+
+        if timeoutSet {
+            limits.Timeout = &timeout
+        }
+    }
+
+    return limits
+}
+
+func nestedError(errorMessage string, err error) (error) {
+    return whisk.MakeWskErrorFromWskError(
+        errors.New(errorMessage),
+        err,
+        whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG,
+        whisk.DISPLAY_USAGE)
+}
+
+func nonNestedError(errorMessage string) (error) {
+    return whisk.MakeWskError(
+        errors.New(errorMessage),
+        whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG,
+        whisk.DISPLAY_USAGE)
+}
+
+func actionParseError(cmd *cobra.Command, args []string, err error) (error) {
+    whisk.Debug(whisk.DbgError, "parseAction(%s, %s) error: %s\n", cmd, args, err)
+
+    errMsg := wski18n.T(
+        "Unable to parse action command arguments: {{.err}}",
+        map[string]interface{}{
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func actionInsertError(action *whisk.Action, err error) (error) {
+    whisk.Debug(whisk.DbgError, "client.Actions.Insert(%#v, false) error: %s\n", action, err)
+
+    errMsg := wski18n.T(
+        "Unable to create action '{{.name}}': {{.err}}",
+        map[string]interface{}{
+            "name": action.Name,
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func parseQualifiedNameError(entityName string, err error) (error) {
+    whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", entityName, err)
+
+    errMsg := wski18n.T(
+        "'{{.name}}' is not a valid qualified name: {{.err}}",
+        map[string]interface{}{
+            "name": entityName,
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func getJSONFromStringsParamError(params []string, keyValueFormat bool, err error) (error) {
+    whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, %t) failed: %s\n", params, keyValueFormat, err)
+
+    errMsg := wski18n.T(
+        "Invalid parameter argument '{{.param}}': {{.err}}",
+        map[string]interface{}{
+            "param": fmt.Sprintf("%#v", params),
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func getJSONFromStringsAnnotError(annots []string, keyValueFormat bool, err error) (error) {
+    whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, %t) failed: %s\n", annots, keyValueFormat, err)
+
+    errMsg := wski18n.T(
+        "Invalid annotation argument '{{.annotation}}': {{.err}}",
+        map[string]interface{}{
+            "annotation": fmt.Sprintf("%#v", annots),
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func invalidFieldFilterError(field string) (error) {
+    errMsg := wski18n.T(
+        "Invalid field filter '{{.arg}}'.",
+        map[string]interface{}{
+            "arg": field,
+        })
+
+    return nonNestedError(errMsg)
+}
+
+func actionDeleteError(entityName string, err error) (error) {
+    whisk.Debug(whisk.DbgError, "client.Actions.Delete(%s) error: %s\n", entityName, err)
+
+    errMsg := wski18n.T(
+        "Unable to delete action '{{.name}}': {{.err}}",
+        map[string]interface{}{
+            "name": entityName,
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func actionGetError(entityName string, err error) (error) {
+    whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", entityName, err)
+
+    errMsg := wski18n.T(
+        "Unable to get action '{{.name}}': {{.err}}",
+        map[string]interface{}{
+            "name": entityName,
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func handleInvocationError(err error, entityName string, parameters interface{}) (error) {
+    whisk.Debug(
+        whisk.DbgError,
+        "client.Actions.Invoke(%s, %s, %t) error: %s\n",
+        entityName, parameters,
+        flags.common.blocking,
+        err)
+
+    errMsg := wski18n.T(
+        "Unable to invoke action '{{.name}}': {{.err}}",
+        map[string]interface{}{
+            "name": entityName,
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func actionListError(entityName string, options *whisk.ActionListOptions, err error) (error) {
+    whisk.Debug(whisk.DbgError, "client.Actions.List(%s, %#v) error: %s\n", entityName, options, err)
+
+    errMsg := wski18n.T(
+        "Unable to obtain the list of actions for namespace '{{.name}}': {{.err}}",
+        map[string]interface{}{
+            "name": getClientNamespace(),
+            "err": err,
+        })
+
+    return nestedError(errMsg, err)
+}
+
+func webInputError(arg string) (error) {
+    errMsg := wski18n.T(
+        "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'.",
+        map[string]interface{}{
+            "arg": arg,
+        })
+
+    return nonNestedError(errMsg)
+}
+
+func zipKindError() (error) {
+    errMsg := wski18n.T("creating an action from a .zip artifact requires specifying the action kind explicitly")
+
+    return nonNestedError(errMsg)
+}
+
+func extensionError(extension string) (error) {
+    errMsg := wski18n.T(
+        "'{{.name}}' is not a supported action runtime",
+        map[string]interface{}{
+            "name": extension,
+        })
+
+    return nonNestedError(errMsg)
+}
+
+func javaEntryError() (error) {
+    errMsg := wski18n.T("Java actions require --main to specify the fully-qualified name of the main class")
+
+    return nonNestedError(errMsg)
+}
+
+func printActionCreated(entityName string) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T(
+            "{{.ok}} created action {{.name}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+            }))
+}
+
+func printActionUpdated(entityName string) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T(
+            "{{.ok}} updated action {{.name}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+            }))
+}
+
+func printBlockingTimeoutMsg(namespace string, entityName string, activationID interface{}) {
+    fmt.Fprintf(
+        colorable.NewColorableStderr(),
+        wski18n.T(
+            "{{.ok}} invoked /{{.namespace}}/{{.name}}, but the request has not yet finished, with id {{.id}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "namespace": boldString(namespace),
+                "name": boldString(entityName),
+                "id": boldString(activationID),
+            }))
+}
+
+func printInvocationMsg(
+    namespace string,
+    entityName string,
+    activationID interface{},
+    response map[string]interface{},
+    outputStream io.Writer) {
+        if !flags.action.result {
+            fmt.Fprintf(
+                outputStream,
+                wski18n.T(
+                    "{{.ok}} invoked /{{.namespace}}/{{.name}} with id {{.id}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "namespace": boldString(namespace),
+                        "name": boldString(entityName),
+                        "id": boldString(activationID),
+                    }))
+        }
+
+        if flags.common.blocking {
+            printJSON(response, outputStream)
+        }
+}
+
+func printActionGetWithField(entityName string, field string, action *whisk.Action) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T(
+            "{{.ok}} got action {{.name}}, displaying field {{.field}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+                "field": boldString(field),
+            }))
+
+    printField(action, field)
+}
+
+func printActionGet(entityName string, action *whisk.Action) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T("{{.ok}} got action {{.name}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+            }))
+
+    printJSON(action)
+}
+
+func printActionDeleted(entityName string) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T(
+            "{{.ok}} deleted action {{.name}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+            }))
+}
+
+// Check if the specified action is a web-action
+func isWebAction(client *whisk.Client, qname QualifiedName) error {
+    var err error = nil
+
+    savedNs := client.Namespace
+    client.Namespace = qname.namespace
+    fullActionName := "/" + qname.namespace + "/" + qname.entityName
+
+    action, _, err := client.Actions.Get(qname.entityName)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", fullActionName, err)
+        whisk.Debug(whisk.DbgError, "Unable to obtain action '%s' for web action validation\n", fullActionName)
+        err = errors.New(wski18n.T("API action does not exist"))
+    } else {
+        err = errors.New(wski18n.T("API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+            map[string]interface{}{"name": fullActionName}))
+        weVal := getValue(action.Annotations, "web-export")
+        if (weVal == nil) {
+            whisk.Debug(whisk.DbgError, "getValue(annotations, web-export) for action %s found no value\n", fullActionName)
+        } else {
+            var webExport bool
+            var ok bool
+            if webExport, ok = weVal.(bool); !ok {
+                whisk.Debug(whisk.DbgError, "web-export annotation value (%v) is not a boolean\n", weVal)
+            } else if !webExport {
+                whisk.Debug(whisk.DbgError, "web-export annotation value is false\n", weVal)
+            } else {
+                err = nil
+            }
+        }
+    }
+
+    client.Namespace = savedNs
+    return err
+}
 
 func init() {
+    actionCreateCmd.Flags().BoolVar(&flags.action.docker, "docker", false, wski18n.T("treat ACTION as docker image path on dockerhub"))
+    actionCreateCmd.Flags().BoolVar(&flags.action.copy, "copy", false, wski18n.T("treat ACTION as the name of an existing action"))
+    actionCreateCmd.Flags().BoolVar(&flags.action.sequence, "sequence", false, wski18n.T("treat ACTION as comma separated sequence of actions to invoke"))
+    actionCreateCmd.Flags().StringVar(&flags.action.kind, "kind", "", wski18n.T("the `KIND` of the action runtime (example: swift:default, nodejs:default)"))
+    actionCreateCmd.Flags().StringVar(&flags.action.main, "main", "", wski18n.T("the name of the action entry point (function or fully-qualified method name when applicable)"))
+    actionCreateCmd.Flags().IntVarP(&flags.action.timeout, "timeout", "t", TIMEOUT_LIMIT, wski18n.T("the timeout `LIMIT` in milliseconds after which the action is terminated"))
+    actionCreateCmd.Flags().IntVarP(&flags.action.memory, "memory", "m", MEMORY_LIMIT, wski18n.T("the maximum memory `LIMIT` in MB for the action"))
+    actionCreateCmd.Flags().IntVarP(&flags.action.logsize, "logsize", "l", LOGSIZE_LIMIT, wski18n.T("the maximum log size `LIMIT` in MB for the action"))
+    actionCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", nil, wski18n.T("annotation values in `KEY VALUE` format"))
+    actionCreateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+    actionCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", nil, wski18n.T("parameter values in `KEY VALUE` format"))
+    actionCreateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+    actionCreateCmd.Flags().StringVar(&flags.action.web, "web", "", wski18n.T("treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"))
 
-	actionCreateCmd.Flags().BoolVar(&flags.action.docker, "docker", false, "treat artifact as docker image path on dockerhub")
-	actionCreateCmd.Flags().BoolVar(&flags.action.copy, "copy", false, "treat artifact as the name of an existing action")
-	actionCreateCmd.Flags().BoolVar(&flags.action.sequence, "sequence", false, "treat artifact as comma separated sequence of actions to invoke")
-	actionCreateCmd.Flags().BoolVar(&flags.action.shared, "shared", false, "shared action (default: private)")
-	actionCreateCmd.Flags().StringVar(&flags.action.lib, "lib", "", "add library to artifact (must be a gzipped tar file)")
-	actionCreateCmd.Flags().StringVar(&flags.action.xPackage, "package", "", "package")
-	actionCreateCmd.Flags().IntVarP(&flags.action.timeout, "timeout", "t", 0, "the timeout limit in miliseconds when the action will be terminated")
-	actionCreateCmd.Flags().IntVarP(&flags.action.memory, "memory", "m", 0, "the memory limit in MB of the container that runs the action")
-	actionCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	actionCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
+    actionUpdateCmd.Flags().BoolVar(&flags.action.docker, "docker", false, wski18n.T("treat ACTION as docker image path on dockerhub"))
+    actionUpdateCmd.Flags().BoolVar(&flags.action.copy, "copy", false, wski18n.T("treat ACTION as the name of an existing action"))
+    actionUpdateCmd.Flags().BoolVar(&flags.action.sequence, "sequence", false, wski18n.T("treat ACTION as comma separated sequence of actions to invoke"))
+    actionUpdateCmd.Flags().StringVar(&flags.action.kind, "kind", "", wski18n.T("the `KIND` of the action runtime (example: swift:default, nodejs:default)"))
+    actionUpdateCmd.Flags().StringVar(&flags.action.main, "main", "", wski18n.T("the name of the action entry point (function or fully-qualified method name when applicable)"))
+    actionUpdateCmd.Flags().IntVarP(&flags.action.timeout, "timeout", "t", TIMEOUT_LIMIT, wski18n.T("the timeout `LIMIT` in milliseconds after which the action is terminated"))
+    actionUpdateCmd.Flags().IntVarP(&flags.action.memory, "memory", "m", MEMORY_LIMIT, wski18n.T("the maximum memory `LIMIT` in MB for the action"))
+    actionUpdateCmd.Flags().IntVarP(&flags.action.logsize, "logsize", "l", LOGSIZE_LIMIT, wski18n.T("the maximum log size `LIMIT` in MB for the action"))
+    actionUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+    actionUpdateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+    actionUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+    actionUpdateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+    actionUpdateCmd.Flags().StringVar(&flags.action.web, "web", "", wski18n.T("treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"))
 
-	actionUpdateCmd.Flags().BoolVar(&flags.action.docker, "docker", false, "treat artifact as docker image path on dockerhub")
-	actionUpdateCmd.Flags().BoolVar(&flags.action.copy, "copy", false, "treat artifact as the name of an existing action")
-	actionUpdateCmd.Flags().BoolVar(&flags.action.sequence, "sequence", false, "treat artifact as comma separated sequence of actions to invoke")
-	actionUpdateCmd.Flags().BoolVar(&flags.action.shared, "shared", false, "shared action (default: private)")
-	actionUpdateCmd.Flags().StringVar(&flags.action.lib, "lib", "", "add library to artifact (must be a gzipped tar file)")
-	actionUpdateCmd.Flags().StringVar(&flags.action.xPackage, "package", "", "package")
-	actionUpdateCmd.Flags().IntVarP(&flags.action.timeout, "timeout", "t", 0, "the timeout limit in miliseconds when the action will be terminated")
-	actionUpdateCmd.Flags().IntVarP(&flags.action.memory, "memory", "m", 0, "the memory limit in MB of the container that runs the action")
-	actionUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	actionUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
+    actionInvokeCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+    actionInvokeCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+    actionInvokeCmd.Flags().BoolVarP(&flags.common.blocking, "blocking", "b", false, wski18n.T("blocking invoke"))
+    actionInvokeCmd.Flags().BoolVarP(&flags.action.result, "result", "r", false, wski18n.T("blocking invoke; show only activation result (unless there is a failure)"))
 
-	actionInvokeCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "parameters")
-	actionInvokeCmd.Flags().BoolVarP(&flags.common.blocking, "blocking", "b", false, "blocking invoke")
-	actionInvokeCmd.Flags().BoolVarP(&flags.action.result, "result", "r", false, "show only activation result if a blocking activation (unless there is a failure)")
+    actionGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, wski18n.T("summarize action details"))
 
-	actionGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, "summarize entity details")
+    actionListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
+    actionListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
 
-	actionListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, "skip this many entitites from the head of the collection")
-	actionListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, "only return this many entities from the collection")
-	actionListCmd.Flags().BoolVar(&flags.common.full, "full", false, "include full entity description")
-
-	actionCmd.AddCommand(
-		actionCreateCmd,
-		actionUpdateCmd,
-		actionInvokeCmd,
-		actionGetCmd,
-		actionDeleteCmd,
-		actionListCmd,
-	)
+    actionCmd.AddCommand(
+        actionCreateCmd,
+        actionUpdateCmd,
+        actionInvokeCmd,
+        actionGetCmd,
+        actionDeleteCmd,
+        actionListCmd,
+    )
 }
diff --git a/commands/activation.go b/commands/activation.go
index 8408aad..df0b2d5 100644
--- a/commands/activation.go
+++ b/commands/activation.go
@@ -1,262 +1,363 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"errors"
-	"fmt"
-	"os"
-	"os/signal"
-	"syscall"
-	"time"
+    "errors"
+    "fmt"
+    "os"
+    "os/signal"
+    "syscall"
+    "time"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 
-	"github.com/fatih/color"
-	"github.com/spf13/cobra"
+    "github.com/fatih/color"
+    "github.com/spf13/cobra"
 )
 
 const (
-	PollInterval = time.Second * 2
-	Delay        = time.Second * 5
+    PollInterval = time.Second * 2
+    Delay        = time.Second * 5
 )
 
 // activationCmd represents the activation command
 var activationCmd = &cobra.Command{
-	Use:   "activation",
-	Short: "work with activations",
+    Use:   "activation",
+    Short: wski18n.T("work with activations"),
 }
 
 var activationListCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list activations",
+    Use:   "list [NAMESPACE or NAME]",
+    Short: wski18n.T("list activations"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        qName := QualifiedName{}
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		qName := qualifiedName{}
-		if len(args) == 1 {
-			qName, err = parseQualifiedName(args[0])
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
-			ns := qName.namespace
-			if len(ns) == 0 {
-				err = errors.New("No valid namespace detected.  Make sure that namespace argument is preceded by a \"/\"")
-				fmt.Printf("error: %s\n", err)
-				return
-			}
+        // Specifying an activation item name filter is optional
+        if len(args) == 1 {
+            whisk.Debug(whisk.DbgInfo, "Activation item name filter '%s' provided\n", args[0])
+            qName, err = parseQualifiedName(args[0])
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+                errStr := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                        map[string]interface{}{"name": args[0], "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            ns := qName.namespace
+            if len(ns) == 0 {
+                whisk.Debug(whisk.DbgError, "Namespace '%s' is invalid\n", ns)
+                errStr := wski18n.T("Namespace '{{.name}}' is invalid", map[string]interface{}{"name": ns})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
 
-			client.Namespace = ns
+            client.Namespace = ns
+        } else if whiskErr := checkArgs(args, 0, 1, "Activation list",
+                wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-			if pkg := qName.packageName; len(pkg) > 0 {
-				// todo :: scope call to package
-			}
-		}
+        options := &whisk.ActivationListOptions{
+            Name:  qName.entityName,
+            Limit: flags.common.limit,
+            Skip:  flags.common.skip,
+            Upto:  flags.activation.upto,
+            Since: flags.activation.since,
+            Docs:  flags.common.full,
+        }
+        activations, _, err := client.Activations.List(options)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Activations.List() error: %s\n", err)
+            errStr := wski18n.T("Unable to obtain the list of activations for namespace '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": getClientNamespace(), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		options := &whisk.ActivationListOptions{
-			Name:  flags.activation.action,
-			Limit: flags.common.limit,
-			Skip:  flags.common.skip,
-			Upto:  flags.activation.upto,
-			Since: flags.activation.since,
-			Docs:  flags.common.full,
-		}
-		activations, _, err := client.Activations.List(options)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		printList(activations)
-	},
+        // When the --full (URL contains "?docs=true") option is specified, display the entire activation details
+        if options.Docs == true {
+            printFullActivationList(activations)
+        } else {
+            printList(activations)
+        }
+
+        return nil
+    },
 }
 
 var activationGetCmd = &cobra.Command{
-	Use:   "get <id string>",
-	Short: "get activation",
+    Use:   "get ACTIVATION_ID [FIELD_FILTER]",
+    Short: wski18n.T("get activation"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var field string
 
-	Run: func(cmd *cobra.Command, args []string) {
-		if len(args) != 1 {
-			err := errors.New("Invalid ID argument")
-			fmt.Println(err)
-			return
-		}
-		id := args[0]
-		activation, _, err := client.Activations.Get(id)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 2, "Activation get",
+                wski18n.T("An activation ID is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		if flags.common.summary {
-			fmt.Printf("activation result for /%s/%s (%s at %s)", activation.Namespace, activation.Name, activation.Response.Status, time.Unix(activation.End/1000, 0))
-			printJSON(activation.Response.Result)
-		} else {
-			fmt.Printf("%s got activation %s\n", color.GreenString("ok:"), boldString(id))
-			printJSON(activation)
-		}
+        if len(args) > 1 {
+            field = args[1]
 
-	},
+            if !fieldExists(&whisk.Activation{}, field) {
+                errMsg := wski18n.T("Invalid field filter '{{.arg}}'.", map[string]interface{}{"arg": field})
+                whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        id := args[0]
+        activation, _, err := client.Activations.Get(id)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Activations.Get(%s) failed: %s\n", id, err)
+            errStr := wski18n.T("Unable to get activation '{{.id}}': {{.err}}",
+                    map[string]interface{}{"id": id, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        if flags.common.summary {
+            fmt.Printf(
+                wski18n.T("activation result for /{{.namespace}}/{{.name}} ({{.status}} at {{.time}})\n",
+                    map[string]interface{}{
+                        "namespace": activation.Namespace,
+                        "name": activation.Name,
+                        "status": activation.Response.Status,
+                        "time": time.Unix(activation.End/1000, 0)}))
+            printJSON(activation.Response.Result)
+        } else {
+
+            if len(field) > 0 {
+                fmt.Fprintf(color.Output,
+                    wski18n.T("{{.ok}} got activation {{.id}}, displaying field {{.field}}\n",
+                        map[string]interface{}{"ok": color.GreenString("ok:"), "id": boldString(id),
+                        "field": boldString(field)}))
+                printField(activation, field)
+            } else {
+                fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got activation {{.id}}\n",
+                        map[string]interface{}{"ok": color.GreenString("ok:"), "id": boldString(id)}))
+                printJSON(activation)
+            }
+        }
+
+        return nil
+    },
 }
 
 var activationLogsCmd = &cobra.Command{
-	Use:   "logs",
-	Short: "get the logs of an activation",
+    Use:   "logs ACTIVATION_ID",
+    Short: wski18n.T("get the logs of an activation"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
 
-	Run: func(cmd *cobra.Command, args []string) {
-		if len(args) != 1 {
-			err := errors.New("Invalid ID argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 1, "Activation logs",
+                wski18n.T("An activation ID is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		id := args[0]
-		activation, _, err := client.Activations.Logs(id)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        id := args[0]
+        activation, _, err := client.Activations.Logs(id)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Activations.Logs(%s) failed: %s\n", id, err)
+            errStr := wski18n.T("Unable to get logs for activation '{{.id}}': {{.err}}",
+                map[string]interface{}{"id": id, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		fmt.Printf("%s got activation %s logs\n", color.GreenString("ok:"), boldString(id))
-
-		printJSON(activation.Logs)
-	},
+        printActivationLogs(activation.Logs)
+        return nil
+    },
 }
 
 var activationResultCmd = &cobra.Command{
-	Use:   "result",
-	Short: "get the result of an activation",
+    Use:   "result ACTIVATION_ID",
+    Short: "get the result of an activation",
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
 
-	Run: func(cmd *cobra.Command, args []string) {
-		if len(args) != 1 {
-			err := errors.New("Invalid ID argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 1, "Activation result",
+                wski18n.T("An activation ID is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		id := args[0]
-		result, _, err := client.Activations.Result(id)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        id := args[0]
+        result, _, err := client.Activations.Result(id)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Activations.result(%s) failed: %s\n", id, err)
+            errStr := wski18n.T("Unable to get result for activation '{{.id}}': {{.err}}",
+                    map[string]interface{}{"id": id, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		fmt.Printf("%s got activation %s result\n", color.GreenString("ok:"), boldString(id))
-		printJSON(result)
-	},
+        printJSON(result.Result)
+        return nil
+    },
 }
 
 var activationPollCmd = &cobra.Command{
-	Use:   "poll <namespace string>",
-	Short: "poll continuously for log messages from currently running actions",
+    Use:   "poll [NAMESPACE]",
+    Short: wski18n.T("poll continuously for log messages from currently running actions"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var name string
+        var pollSince int64 // Represents an instant in time (in milliseconds since Jan 1 1970)
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var name string
-		if len(args) == 1 {
-			name = args[0]
-		}
+        if len(args) == 1 {
+            name = args[0]
+        } else if whiskErr := checkArgs(args, 0, 1, "Activation poll",
+                wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		c := make(chan os.Signal, 1)
-		signal.Notify(c, os.Interrupt)
-		signal.Notify(c, syscall.SIGTERM)
-		go func() {
-			<-c
-			fmt.Println("Poll terminated")
-			os.Exit(1)
-		}()
-		fmt.Println("Enter Ctrl-c to exit.")
+        c := make(chan os.Signal, 1)
+        signal.Notify(c, os.Interrupt)
+        signal.Notify(c, syscall.SIGTERM)
+        go func() {
+            <-c
+            fmt.Println(wski18n.T("Poll terminated"))
+            os.Exit(1)
+        }()
+        fmt.Println(wski18n.T("Enter Ctrl-c to exit."))
 
-		pollSince := time.Now()
-		reported := []string{}
+        // Map used to track activation records already displayed to the console
+        reported := make(map[string]bool)
 
-		if flags.activation.sinceSeconds+
-			flags.activation.sinceMinutes+
-			flags.activation.sinceHours+
-			flags.activation.sinceDays ==
-			0 {
-			options := &whisk.ActivationListOptions{
-				Limit: 1,
-				Docs:  true,
-			}
-			activationList, _, _ := client.Activations.List(options)
-			if len(activationList) > 0 {
-				lastActivation := activationList[0]
-				pollSince = time.Unix(lastActivation.Start+1, 0).Add(Delay)
-			}
-		} else {
-			t0 := time.Now()
+        if flags.activation.sinceSeconds+
+        flags.activation.sinceMinutes+
+        flags.activation.sinceHours+
+        flags.activation.sinceDays ==
+        0 {
+            options := &whisk.ActivationListOptions{
+                Limit: 1,
+                Docs:  true,
+            }
+            activationList, _, err := client.Activations.List(options)
+            if err != nil {
+                whisk.Debug(whisk.DbgWarn, "client.Activations.List() error: %s\n", err)
+                whisk.Debug(whisk.DbgWarn, "Ignoring client.Activations.List failure; polling for activations since 'now'\n")
+                pollSince = time.Now().Unix() * 1000    // Convert to milliseconds
+            } else {
+                if len(activationList) > 0 {
+                    lastActivation := activationList[0]     // Activation.Start is in milliseconds since Jan 1 1970
+                    pollSince = lastActivation.Start + 1    // Use it's start time as the basis of the polling
+                }
+            }
+        } else {
+            pollSince = time.Now().Unix() * 1000    // Convert to milliseconds
 
-			duration, err := time.ParseDuration(fmt.Sprintf("%ds %dm %dh",
-				flags.activation.sinceSeconds,
-				flags.activation.sinceMinutes,
-				flags.activation.sinceHours+
-					flags.activation.sinceDays*24,
-			))
-			if err == nil {
-				pollSince = t0.Add(-duration)
-			}
-		}
+            // ParseDuration takes a string like "2h45m15s"; create this duration string from the command arguments
+            durationStr := fmt.Sprintf("%dh%dm%ds",
+                flags.activation.sinceHours + flags.activation.sinceDays*24,
+                flags.activation.sinceMinutes,
+                flags.activation.sinceSeconds,
+            )
+            duration, err := time.ParseDuration(durationStr)
+            if err == nil {
+                pollSince = pollSince - duration.Nanoseconds()/1000/1000    // Convert to milliseconds
+            } else {
+                whisk.Debug(whisk.DbgError, "time.ParseDuration(%s) failure: %s\n", durationStr, err)
+            }
+        }
 
-		fmt.Println("Polling for logs")
-		localStartTime := time.Now()
-		for {
-			if flags.activation.exit > 0 {
-				localDuration := time.Since(localStartTime)
-				if int(localDuration.Seconds()) > flags.activation.exit {
-					return
-				}
-			}
+        fmt.Printf(wski18n.T("Polling for activation logs\n"))
+        whisk.Verbose("Polling starts from %s\n", time.Unix(pollSince/1000, 0))
+        localStartTime := time.Now()
 
-			options := &whisk.ActivationListOptions{
-				Name:  name,
-				Since: pollSince.Unix(),
-				Docs:  true,
-			}
+        // Polling loop
+        for {
+            if flags.activation.exit > 0 {
+                localDuration := time.Since(localStartTime)
+                if int(localDuration.Seconds()) > flags.activation.exit {
+                    whisk.Debug(whisk.DbgInfo, "Poll time (%d seconds) expired; polling loop stopped\n", flags.activation.exit)
+                    return nil
+                }
+            }
+            whisk.Verbose("Polling for activations since %s\n", time.Unix(pollSince/1000, 0))
+            options := &whisk.ActivationListOptions{
+                Name:  name,
+                Since: pollSince,
+                Docs:  true,
+                Limit: 0,
+                Skip: 0,
+            }
 
-			activations, _, err := client.Activations.List(options)
-			if err != nil {
-				continue
-			}
+            activations, _, err := client.Activations.List(options)
+            if err != nil {
+                whisk.Debug(whisk.DbgWarn, "client.Activations.List() error: %s\n", err)
+                whisk.Debug(whisk.DbgWarn, "Ignoring client.Activations.List failure; continuing to poll for activations\n")
+                continue
+            }
 
-			for _, activation := range activations {
-				for _, id := range reported {
-					if id == activation.ActivationID {
-						continue
-					}
-				}
-				fmt.Printf("\nActivation: %s (%s)\n", activation.Name, activation.ActivationID)
-				printJSON(activation.Logs)
-
-				reported = append(reported, activation.ActivationID)
-				if activationTime := time.Unix(activation.Start, 0); activationTime.After(pollSince) {
-					pollSince = activationTime
-				}
-			}
-			time.Sleep(time.Second * 2)
-		}
-	},
+            for _, activation := range activations {
+                if reported[activation.ActivationID] == true {
+                    continue
+                } else {
+                    fmt.Printf(
+                        wski18n.T("\nActivation: {{.name}} ({{.id}})\n",
+                            map[string]interface{}{"name": activation.Name, "id": activation.ActivationID}))
+                    printJSON(activation.Logs)
+                    reported[activation.ActivationID] = true
+                }
+            }
+            time.Sleep(time.Second * 2)
+        }
+        return nil
+    },
 }
 
 func init() {
+    activationListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of activations from the result"))
+    activationListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of activations from the collection"))
+    activationListCmd.Flags().BoolVarP(&flags.common.full, "full", "f", false, wski18n.T("include full activation description"))
+    activationListCmd.Flags().Int64Var(&flags.activation.upto, "upto", 0, wski18n.T("return activations with timestamps earlier than `UPTO`; measured in milliseconds since Th, 01, Jan 1970"))
+    activationListCmd.Flags().Int64Var(&flags.activation.since, "since", 0, wski18n.T("return activations with timestamps later than `SINCE`; measured in milliseconds since Th, 01, Jan 1970"))
 
-	activationListCmd.Flags().StringVarP(&flags.activation.action, "action", "a", "", "retrieve activations for action")
-	activationListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, "skip this many entitites from the head of the collection")
-	activationListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, "only return this many entities from the collection")
-	activationListCmd.Flags().BoolVarP(&flags.common.full, "full", "f", false, "include full entity description")
-	activationListCmd.Flags().Int64Var(&flags.activation.upto, "upto", 0, "return activations with timestamps earlier than UPTO; measured in miliseconds since Th, 01, Jan 1970")
-	activationListCmd.Flags().Int64Var(&flags.activation.since, "since", 0, "return activations with timestamps earlier than UPTO; measured in miliseconds since Th, 01, Jan 1970")
+    activationGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, wski18n.T("summarize activation details"))
 
-	activationGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, "summarize entity details")
+    activationPollCmd.Flags().IntVarP(&flags.activation.exit, "exit", "e", 0, wski18n.T("stop polling after `SECONDS` seconds"))
+    activationPollCmd.Flags().IntVar(&flags.activation.sinceSeconds, "since-seconds", 0, wski18n.T("start polling for activations `SECONDS` seconds ago"))
+    activationPollCmd.Flags().IntVar(&flags.activation.sinceMinutes, "since-minutes", 0, wski18n.T("start polling for activations `MINUTES` minutes ago"))
+    activationPollCmd.Flags().IntVar(&flags.activation.sinceHours, "since-hours", 0, wski18n.T("start polling for activations `HOURS` hours ago"))
+    activationPollCmd.Flags().IntVar(&flags.activation.sinceDays, "since-days", 0, wski18n.T("start polling for activations `DAYS` days ago"))
 
-	activationPollCmd.Flags().IntVarP(&flags.activation.exit, "exit", "e", 0, "exit after this many seconds")
-	activationPollCmd.Flags().IntVar(&flags.activation.sinceSeconds, "since-seconds", 0, "start polling for activations this many seconds ago")
-	activationPollCmd.Flags().IntVar(&flags.activation.sinceMinutes, "since-minutes", 0, "start polling for activations this many minutes ago")
-	activationPollCmd.Flags().IntVar(&flags.activation.sinceHours, "since-hours", 0, "start polling for activations this many hours ago")
-	activationPollCmd.Flags().IntVar(&flags.activation.sinceDays, "since-days", 0, "start polling for activations this many days ago")
-
-	activationCmd.AddCommand(
-		activationListCmd,
-		activationGetCmd,
-		activationLogsCmd,
-		activationResultCmd,
-		activationPollCmd,
-	)
+    activationCmd.AddCommand(
+        activationListCmd,
+        activationGetCmd,
+        activationLogsCmd,
+        activationResultCmd,
+        activationPollCmd,
+    )
 }
diff --git a/commands/api.go b/commands/api.go
new file mode 100644
index 0000000..430dc38
--- /dev/null
+++ b/commands/api.go
@@ -0,0 +1,1487 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package commands
+
+import (
+    "errors"
+    "fmt"
+    "reflect"
+    "strconv"
+    "strings"
+
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
+
+    "github.com/fatih/color"
+    "github.com/spf13/cobra"
+    "encoding/json"
+)
+
+//////////////
+// Commands //
+//////////////
+
+var apiExperimentalCmd = &cobra.Command{
+    Use:   "api-experimental",
+    Short: wski18n.T("work with APIs (experimental)"),
+}
+
+var apiCmd = &cobra.Command{
+    Use:   "api",
+    Short: wski18n.T("work with APIs"),
+}
+
+var apiCreateCmd = &cobra.Command{
+    Use:           "create ([BASE_PATH] API_PATH API_VERB ACTION] | --config-file CFG_FILE) ",
+    Short:         wski18n.T("create a new API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+
+        var api *whisk.Api
+        var err error
+
+        if (len(args) == 0 && flags.api.configfile == "") {
+            whisk.Debug(whisk.DbgError, "No swagger file and no arguments\n")
+            errMsg := wski18n.T("Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return whiskErr
+        } else if (len(args) == 0 && flags.api.configfile != "") {
+            api, err = parseSwaggerApi()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseSwaggerApi() error: %s\n", err)
+                errMsg := wski18n.T("Unable to parse swagger file: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        } else {
+            if whiskErr := checkArgs(args, 3, 4, "Api create",
+                wski18n.T("Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")); whiskErr != nil {
+                return whiskErr
+            }
+            api, err = parseApi(cmd, args)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseApi(%s, %s) error: %s\n", cmd, args, err)
+                errMsg := wski18n.T("Unable to parse api command arguments: {{.err}}",
+                    map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        apiCreateReq := new(whisk.ApiCreateRequest)
+        apiCreateReq.ApiDoc = api
+        apiCreateReqOptions := new(whisk.ApiCreateRequestOptions)
+        retApi, _, err := client.Apis.Insert(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.Insert(%#v, false) error: %s\n", api, err)
+            errMsg := wski18n.T("Unable to create API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_NETWORK,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (api.Swagger == "") {
+            baseUrl := retApi.BaseUrl
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": strings.TrimSuffix(api.GatewayBasePath, "/")+api.GatewayRelPath,
+                        "verb": api.GatewayMethod,
+                        "name": boldString("/"+api.Action.Namespace+"/"+api.Action.Name),
+                        "fullpath": strings.TrimSuffix(baseUrl, "/")+api.GatewayRelPath,
+                    }))
+        } else {
+            whisk.Debug(whisk.DbgInfo, "Processing swagger based create API response\n")
+            baseUrl := retApi.BaseUrl
+            for path, _ := range retApi.Swagger.Paths {
+                managedUrl := strings.TrimSuffix(baseUrl, "/")+path
+                whisk.Debug(whisk.DbgInfo, "Managed path: %s\n",managedUrl)
+                for op, opv  := range retApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "Path operation: %s\n", op)
+                    fmt.Fprintf(color.Output,
+                        wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                            map[string]interface{}{
+                                "ok": color.GreenString("ok:"),
+                                "path": path,
+                                "verb": op,
+                                "name": boldString(opv.XOpenWhisk.ActionName),
+                                "fullpath": managedUrl,
+                            }))
+                }
+            }
+        }
+
+
+        return nil
+    },
+}
+
+//var apiUpdateCmd = &cobra.Command{
+//    Use:           "update API_PATH API_VERB ACTION",
+//    Short:         wski18n.T("update an existing API"),
+//    SilenceUsage:  true,
+//    SilenceErrors: true,
+//    PreRunE:       setupClientConfig,
+//    RunE: func(cmd *cobra.Command, args []string) error {
+//
+//        if whiskErr := checkArgs(args, 3, 3, "Api update",
+//            wski18n.T("An API path, an API verb, and an action name are required.")); whiskErr != nil {
+//            return whiskErr
+//        }
+//
+//        api, err := parseApi(cmd, args)
+//        if err != nil {
+//            whisk.Debug(whisk.DbgError, "parseApi(%s, %s) error: %s\n", cmd, args, err)
+//            errMsg := wski18n.T("Unable to parse API command arguments: {{.err}}", map[string]interface{}{"err": err})
+//            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+//                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+//            return whiskErr
+//        }
+//        sendApi := new(whisk.ApiCreateRequest)
+//        sendApi.ApiDoc = api
+//
+//        retApi, _, err := client.Apis.Insert(sendApi, true)
+//        if err != nil {
+//            whisk.Debug(whisk.DbgError, "client.Apis.Insert(%#v, %t, false) error: %s\n", api, err)
+//            errMsg := wski18n.T("Unable to update API: {{.err}}", map[string]interface{}{"err": err})
+//            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_NETWORK,
+//                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+//            return whiskErr
+//        }
+//
+//        fmt.Fprintf(color.Output,
+//            wski18n.T("{{.ok}} updated API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+//                map[string]interface{}{
+//                    "ok": color.GreenString("ok:"),
+//                    "path": api.GatewayRelPath,
+//                    "verb": api.GatewayMethod,
+//                    "name": boldString("/"+api.Action.Name),
+//                    "fullpath": getManagedUrl(retApi, api.GatewayRelPath, api.GatewayMethod),
+//                }))
+//        return nil
+//    },
+//}
+
+var apiGetCmd = &cobra.Command{
+    Use:           "get BASE_PATH | API_NAME",
+    Short:         wski18n.T("get API details"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var isBasePathArg bool = true
+
+        if whiskErr := checkArgs(args, 1, 1, "Api get",
+            wski18n.T("An API base path or API name is required.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.ApiBasePath = args[0]
+        retApi, _, err := client.Apis.Get(apiGetReq, apiGetReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+            errMsg := wski18n.T("Unable to get API '{{.name}}': {{.err}}", map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        whisk.Debug(whisk.DbgInfo, "client.Apis.Get returned: %#v\n", retApi)
+
+        var displayResult interface{} = nil
+        if (flags.common.detail) {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+                retApi.Apis[0].ApiValue != nil) {
+                displayResult = retApi.Apis[0].ApiValue
+            } else {
+                whisk.Debug(whisk.DbgError, "No result object returned\n")
+            }
+        } else {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+                retApi.Apis[0].ApiValue != nil &&
+                retApi.Apis[0].ApiValue.Swagger != nil) {
+                  displayResult = retApi.Apis[0].ApiValue.Swagger
+            } else {
+                  whisk.Debug(whisk.DbgError, "No swagger returned\n")
+            }
+        }
+        if (displayResult == nil) {
+            var errMsg string
+            if (isBasePathArg) {
+                errMsg = wski18n.T("API does not exist for basepath {{.basepath}}",
+                    map[string]interface{}{"basepath": args[0]})
+            } else {
+                errMsg = wski18n.T("API does not exist for API name {{.apiname}}",
+                    map[string]interface{}{"apiname": args[0]})
+            }
+
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        printJSON(displayResult)
+
+        return nil
+    },
+}
+
+var apiDeleteCmd = &cobra.Command{
+    Use:           "delete BASE_PATH | API_NAME [API_PATH [API_VERB]]",
+    Short:         wski18n.T("delete an API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE:          func(cmd *cobra.Command, args []string) error {
+        if whiskErr := checkArgs(args, 1, 3, "Api delete",
+            wski18n.T("An API base path or API name is required.  An optional API relative path and operation may also be provided.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiDeleteReq := new(whisk.ApiDeleteRequest)
+        apiDeleteReqOptions := new(whisk.ApiDeleteRequestOptions)
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        } else {
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        }
+
+        if (len(args) > 1) {
+            // Is the API path valid?
+            if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiRelPath = args[1]
+        }
+        if (len(args) > 2) {
+            // Is the API verb valid?
+            if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiVerb = strings.ToUpper(args[2])
+        }
+
+        _, err := client.Apis.Delete(apiDeleteReq, apiDeleteReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.Delete(%#v, %#v) error: %s\n", apiDeleteReq, apiDeleteReqOptions, err)
+            errMsg := wski18n.T("Unable to delete API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (len(args) == 1) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted API {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else if (len(args) == 2 ) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "verb": apiDeleteReqOptions.ApiVerb,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        }
+
+        return nil
+    },
+}
+
+var fmtString = "%-30s %7s %20s  %s\n"
+var apiListCmd = &cobra.Command{
+    Use:           "list [[BASE_PATH | API_NAME] [API_PATH [API_VERB]]",
+    Short:         wski18n.T("list APIs"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var retApiList *whisk.ApiListResponse
+        var retApi *whisk.ApiGetResponse
+        var retApiArray *whisk.RetApiArray
+
+        if whiskErr := checkArgs(args, 0, 3, "Api list",
+            wski18n.T("Optional parameters are: API base path (or API name), API relative path and operation.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        // Get API request body
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReq.Namespace = client.Config.Namespace
+
+        // Get API request options
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+
+        // List API request query parameters
+        apiListReqOptions := new(whisk.ApiListRequestOptions)
+        apiListReqOptions.Limit = flags.common.limit
+        apiListReqOptions.Skip = flags.common.skip
+
+        if (len(args) == 0) {
+            retApiList, _, err = client.Apis.List(apiListReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.List(%#v) error: %s\n", apiListReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.List returned: %#v (%+v)\n", retApiList, retApiList)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArray)(retApiList)
+        } else {
+            // The first argument is either a basepath (must start with /) or an API name
+            apiGetReqOptions.ApiBasePath = args[0]
+            if (len(args) > 1) {
+                // Is the API path valid?
+                if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiRelPath = args[1]
+            }
+            if (len(args) > 2) {
+                // Is the API verb valid?
+                if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiVerb = strings.ToUpper(args[2])
+            }
+
+            retApi, _, err = client.Apis.Get(apiGetReq, apiGetReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.Get returned: %#v\n", retApi)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArray)(retApi)
+        }
+
+        // Display the APIs - applying any specified filtering
+        if (flags.common.full) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} APIs\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                    }))
+
+            for i:=0; i<len(retApiArray.Apis); i++ {
+                printFilteredListApi(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions))
+            }
+        } else {
+            // Dynamically create the output format string based on the maximum size of the
+            // fully qualified action name and the API Name.
+            maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSize(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+            maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSize(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+            fmtString = "%-"+strconv.Itoa(maxActionNameSize)+"s %7s %"+strconv.Itoa(maxApiNameSize+1)+"s  %s\n"
+
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} APIs\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                    }))
+            fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+
+            for i:=0; i<len(retApiArray.Apis); i++ {
+                printFilteredListRow(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions), maxActionNameSize, maxApiNameSize)
+            }
+        }
+
+        return nil
+    },
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API endpoint matching the filtering criteria, display
+ * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url)
+ */
+func printFilteredListApi(resultApi *whisk.RetApi, api *whisk.ApiOptions) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    basePath := resultApi.Swagger.BasePath
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "apiGetCmd: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "apiGetCmd: operation matches: %#v\n", opv)
+                        var actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        fmt.Printf("%s: %s\n", wski18n.T("Action"), actionName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("API Name"), apiName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Base path"), basePath)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Path"), path)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Verb"), op)
+                        fmt.Printf("  %s: %s\n", wski18n.T("URL"), baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API matching the filtering criteria, display the API
+ * on a single line (action name, verb, api name, api gw url).
+ *
+ * NOTE: Large action name and api name value will be truncated by their associated max size parameters.
+ */
+func printFilteredListRow(resultApi *whisk.RetApi, api *whisk.ApiOptions, maxActionNameSize int, maxApiNameSize int) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "apiGetCmd: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "apiGetCmd: operation matches: %#v\n", opv)
+                        var actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        fmt.Printf(fmtString,
+                            actionName[0 : min(len(actionName), maxActionNameSize)],
+                            op,
+                            apiName[0 : min(len(apiName), maxApiNameSize)],
+                            baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+func getLargestActionNameSize(retApiArray *whisk.RetApiArray, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            var fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                            if (len(fullActionName) > maxNameSize) {
+                                maxNameSize = len(fullActionName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+func getLargestApiNameSize(retApiArray *whisk.RetApiArray, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        apiName := resultApi.Swagger.Info.Title
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            if (len(apiName) > maxNameSize) {
+                                maxNameSize = len(apiName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+/*
+ * if # args = 4
+ * args[0] = API base path
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ *
+ * if # args = 3
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ */
+func parseApi(cmd *cobra.Command, args []string) (*whisk.Api, error) {
+    var err error
+    var basepath string = "/"
+    var apiname string
+    var basepathArgIsApiName = false;
+
+    api := new(whisk.Api)
+
+    if (len(args) > 3) {
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            basepathArgIsApiName = true;
+        }
+        basepath = args[0]
+
+        // Shift the args so the remaining code works with or without the explicit base path arg
+        args = args[1:]
+    }
+
+    // Is the API path valid?
+    if (len(args) > 0) {
+        if whiskErr, ok := isValidRelpath(args[0]); !ok {
+            return nil, whiskErr
+        }
+        api.GatewayRelPath = args[0]    // Maintain case as URLs may be case-sensitive
+    }
+
+    // Is the API verb valid?
+    if (len(args) > 1) {
+        if whiskErr, ok := IsValidApiVerb(args[1]); !ok {
+            return nil, whiskErr
+        }
+        api.GatewayMethod = strings.ToUpper(args[1])
+    }
+
+    // Is the specified action name valid?
+    var qName QualifiedName
+    if (len(args) == 3) {
+        qName = QualifiedName{}
+        qName, err = parseQualifiedName(args[2])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[2], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name: {{.err}}",
+                map[string]interface{}{"name": args[2], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, whiskErr
+        }
+        if (qName.entityName == "") {
+            whisk.Debug(whisk.DbgError, "Action name '%s' is invalid\n", args[2])
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name.", map[string]interface{}{"name": args[2]})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, whiskErr
+        }
+    }
+
+    if ( len(flags.api.apiname) > 0 ) {
+        if (basepathArgIsApiName) {
+            // Specifying API name as argument AND as a --apiname option value is invalid
+            whisk.Debug(whisk.DbgError, "API is specified as an argument '%s' and as a flag '%s'\n", basepath, flags.api.apiname)
+            errMsg := wski18n.T("An API name can only be specified once.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, whiskErr
+        }
+        apiname = flags.api.apiname
+    }
+
+    api.Namespace = client.Config.Namespace
+    api.Action = new(whisk.ApiAction)
+    api.Action.BackendUrl = "https://" + client.Config.Host + "/api/v1/namespaces/" + qName.namespace + "/actions/" + qName.entityName
+    api.Action.BackendMethod = "POST"
+    api.Action.Name = qName.entityName
+    api.Action.Namespace = qName.namespace
+    api.Action.Auth = client.Config.AuthToken
+    api.ApiName = apiname
+    api.GatewayBasePath = basepath
+    if (!basepathArgIsApiName) { api.Id = "API:"+api.Namespace+":"+api.GatewayBasePath }
+
+    whisk.Debug(whisk.DbgInfo, "Parsed api struct: %#v\n", api)
+    return api, nil
+}
+
+func parseSwaggerApi() (*whisk.Api, error) {
+    // Test is for completeness, but this situation should only arise due to an internal error
+    if ( len(flags.api.configfile) == 0 ) {
+        whisk.Debug(whisk.DbgError, "No swagger file is specified\n")
+        errMsg := wski18n.T("A configuration file was not specified.")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg),whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    swagger, err:= readFile(flags.api.configfile)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error reading swagger file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    // Parse the JSON into a swagger object
+    swaggerObj := new(whisk.ApiSwagger)
+    err = json.Unmarshal([]byte(swagger), swaggerObj)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "JSON parse of `%s' error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error parsing swagger file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if (swaggerObj.BasePath == "" || swaggerObj.SwaggerName == "" || swaggerObj.Info == nil || swaggerObj.Paths == nil) {
+        whisk.Debug(whisk.DbgError, "Swagger file is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file is invalid (missing basePath, info, paths, or swagger fields)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if _, ok := isValidBasepath(swaggerObj.BasePath); !ok {
+        whisk.Debug(whisk.DbgError, "Swagger file basePath is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file basePath must start with a leading slash (/)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    api := new(whisk.Api)
+    api.Namespace = client.Config.Namespace
+    api.Swagger = swagger
+
+    return api, nil
+}
+
+func IsValidApiVerb(verb string) (error, bool) {
+    // Is the API verb valid?
+    if _, ok := whisk.ApiVerbs[strings.ToUpper(verb)]; !ok {
+        whisk.Debug(whisk.DbgError, "Invalid API verb: %s\n", verb)
+        errMsg := wski18n.T("'{{.verb}}' is not a valid API verb.  Valid values are: {{.verbs}}",
+                map[string]interface{}{
+                    "verb": verb,
+                    "verbs": reflect.ValueOf(whisk.ApiVerbs).MapKeys()})
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr, false
+    }
+    return nil, true
+}
+
+func hasPathPrefix(path string) (error, bool) {
+    if (! strings.HasPrefix(path, "/")) {
+        whisk.Debug(whisk.DbgError, "path does not begin with '/': %s\n", path)
+        errMsg := wski18n.T("'{{.path}}' must begin with '/'.",
+                map[string]interface{}{
+                    "path": path,
+                })
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr, false
+    }
+    return nil, true
+}
+
+func isValidBasepath(basepath string) (error, bool) {
+    if whiskerr, ok := hasPathPrefix(basepath); !ok {
+        return whiskerr, false
+    }
+    return nil, true
+}
+
+func isValidRelpath(relpath string) (error, bool) {
+    if whiskerr, ok := hasPathPrefix(relpath); !ok {
+        return whiskerr, false
+    }
+    return nil, true
+}
+
+
+/*
+ * Pull the managedUrl (external API URL) from the API configuration
+ */
+func getManagedUrl(api *whisk.RetApi, relpath string, operation string) (url string) {
+    baseUrl := strings.TrimSuffix(api.BaseUrl, "/")
+    whisk.Debug(whisk.DbgInfo, "getManagedUrl: baseUrl = %s, relpath = %s, operation = %s\n", baseUrl, relpath, operation)
+    for path, _ := range api.Swagger.Paths {
+        whisk.Debug(whisk.DbgInfo, "getManagedUrl: comparing api relpath: %s\n", path)
+        if (path == relpath) {
+            whisk.Debug(whisk.DbgInfo, "getManagedUrl: relpath matches '%s'\n", relpath)
+            for op, _  := range api.Swagger.Paths[path] {
+                whisk.Debug(whisk.DbgInfo, "getManagedUrl: comparing operation: '%s'\n", op)
+                if (strings.ToLower(op) == strings.ToLower(operation)) {
+                    whisk.Debug(whisk.DbgInfo, "getManagedUrl: operation matches: %s\n", operation)
+                    url = baseUrl+path
+                }
+            }
+        }
+    }
+    return url
+}
+
+/////////////
+// V2 Cmds //
+/////////////
+var apiCreateCmdV2 = &cobra.Command{
+    Use:           "create ([BASE_PATH] API_PATH API_VERB ACTION] | --config-file CFG_FILE) ",
+    Short:         wski18n.T("create a new API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+
+        var api *whisk.Api
+        var err error
+        var qname *QualifiedName
+
+        if (len(args) == 0 && flags.api.configfile == "") {
+            whisk.Debug(whisk.DbgError, "No swagger file and no arguments\n")
+            errMsg := wski18n.T("Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return whiskErr
+        } else if (len(args) == 0 && flags.api.configfile != "") {
+            api, err = parseSwaggerApiV2()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseSwaggerApi() error: %s\n", err)
+                errMsg := wski18n.T("Unable to parse swagger file: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        } else {
+            if whiskErr := checkArgs(args, 3, 4, "Api create",
+                wski18n.T("Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")); whiskErr != nil {
+                return whiskErr
+            }
+            api, qname, err = parseApiV2(cmd, args)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseApiV2(%s, %s) error: %s\n", cmd, args, err)
+                errMsg := wski18n.T("Unable to parse api command arguments: {{.err}}",
+                    map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+
+            // Confirm that the specified action is a web-action
+            err = isWebAction(client, *qname)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "isWebAction(%v) is false: %s\n", qname, err)
+                whiskErr := whisk.MakeWskError(err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        apiCreateReq := new(whisk.ApiCreateRequest)
+        apiCreateReq.ApiDoc = api
+
+        apiCreateReqOptions := new(whisk.ApiCreateRequestOptions)
+        props, _ := readProps(Properties.PropsFile)
+        apiCreateReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiCreateReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiCreateReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+        apiCreateReqOptions.ResponseType = flags.api.resptype
+        whisk.Debug(whisk.DbgInfo, "AccessToken: %s\nSpaceGuid: %s\nResponsType: %s",
+            apiCreateReqOptions.AccessToken, apiCreateReqOptions.SpaceGuid, apiCreateReqOptions.ResponseType)
+
+        retApi, _, err := client.Apis.InsertV2(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.InsertV2(%#v, false) error: %s\n", api, err)
+            errMsg := wski18n.T("Unable to create API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (api.Swagger == "") {
+            baseUrl := retApi.BaseUrl
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": strings.TrimSuffix(api.GatewayBasePath, "/")+api.GatewayRelPath,
+                        "verb": api.GatewayMethod,
+                        "name": boldString("/"+api.Action.Namespace+"/"+api.Action.Name),
+                        "fullpath": strings.TrimSuffix(baseUrl, "/")+api.GatewayRelPath,
+                    }))
+        } else {
+            whisk.Debug(whisk.DbgInfo, "Processing swagger based create API response\n")
+            baseUrl := retApi.BaseUrl
+            for path, _ := range retApi.Swagger.Paths {
+                managedUrl := strings.TrimSuffix(baseUrl, "/")+path
+                whisk.Debug(whisk.DbgInfo, "Managed path: %s\n",managedUrl)
+                for op, opv  := range retApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "Path operation: %s\n", op)
+                    var fqActionName string
+                    if (len(opv.XOpenWhisk.Package) > 0) {
+                        fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                    } else {
+                        fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                    }
+                    whisk.Debug(whisk.DbgInfo, "baseUrl %s  Path %s  Path obj %+v\n", baseUrl, path, opv)
+                    fmt.Fprintf(color.Output,
+                        wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                            map[string]interface{}{
+                                "ok": color.GreenString("ok:"),
+                                "path": strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
+                                "verb": op,
+                                "name": boldString(fqActionName),
+                                "fullpath": managedUrl,
+                            }))
+                }
+            }
+        }
+
+
+        return nil
+    },
+}
+
+var apiGetCmdV2 = &cobra.Command{
+    Use:           "get BASE_PATH | API_NAME",
+    Short:         wski18n.T("get API details"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var isBasePathArg bool = true
+
+        if whiskErr := checkArgs(args, 1, 1, "Api get",
+            wski18n.T("An API base path or API name is required.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.ApiBasePath = args[0]
+        props, _ := readProps(Properties.PropsFile)
+        apiGetReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiGetReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiGetReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        retApi, _, err := client.Apis.GetV2(apiGetReq, apiGetReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.GetV2(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+            errMsg := wski18n.T("Unable to get API '{{.name}}': {{.err}}", map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        whisk.Debug(whisk.DbgInfo, "client.Apis.GetV2 returned: %#v\n", retApi)
+
+        var displayResult interface{} = nil
+        if (flags.common.detail) {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+            retApi.Apis[0].ApiValue != nil) {
+                displayResult = retApi.Apis[0].ApiValue
+            } else {
+                whisk.Debug(whisk.DbgError, "No result object returned\n")
+            }
+        } else {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+            retApi.Apis[0].ApiValue != nil &&
+            retApi.Apis[0].ApiValue.Swagger != nil) {
+                displayResult = retApi.Apis[0].ApiValue.Swagger
+            } else {
+                whisk.Debug(whisk.DbgError, "No swagger returned\n")
+            }
+        }
+        if (displayResult == nil) {
+            var errMsg string
+            if (isBasePathArg) {
+                errMsg = wski18n.T("API does not exist for basepath {{.basepath}}",
+                    map[string]interface{}{"basepath": args[0]})
+            } else {
+                errMsg = wski18n.T("API does not exist for API name {{.apiname}}",
+                    map[string]interface{}{"apiname": args[0]})
+            }
+
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        printJSON(displayResult)
+
+        return nil
+    },
+}
+
+var apiDeleteCmdV2 = &cobra.Command{
+    Use:           "delete BASE_PATH | API_NAME [API_PATH [API_VERB]]",
+    Short:         wski18n.T("delete an API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+
+        if whiskErr := checkArgs(args, 1, 3, "Api delete",
+            wski18n.T("An API base path or API name is required.  An optional API relative path and operation may also be provided.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiDeleteReq := new(whisk.ApiDeleteRequest)
+        apiDeleteReqOptions := new(whisk.ApiDeleteRequestOptions)
+        props, _ := readProps(Properties.PropsFile)
+        apiDeleteReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiDeleteReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiDeleteReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        } else {
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        }
+
+        if (len(args) > 1) {
+            // Is the API path valid?
+            if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiRelPath = args[1]
+        }
+        if (len(args) > 2) {
+            // Is the API verb valid?
+            if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiVerb = strings.ToUpper(args[2])
+        }
+
+        _, err := client.Apis.DeleteV2(apiDeleteReq, apiDeleteReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.DeleteV2(%#v, %#v) error: %s\n", apiDeleteReq, apiDeleteReqOptions, err)
+            errMsg := wski18n.T("Unable to delete API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (len(args) == 1) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted API {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else if (len(args) == 2 ) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "verb": apiDeleteReqOptions.ApiVerb,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        }
+
+        return nil
+    },
+}
+
+var apiListCmdV2 = &cobra.Command{
+    Use:           "list [[BASE_PATH | API_NAME] [API_PATH [API_VERB]]",
+    Short:         wski18n.T("list APIs"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var retApiList *whisk.ApiListResponseV2
+        var retApi *whisk.ApiGetResponseV2
+        var retApiArray *whisk.RetApiArrayV2
+
+        if whiskErr := checkArgs(args, 0, 3, "Api list",
+            wski18n.T("Optional parameters are: API base path (or API name), API relative path and operation.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        props, _ := readProps(Properties.PropsFile)
+        spaceguid := strings.Split(props["AUTH"], ":")[0]
+        var accesstoken string = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            accesstoken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        // Get API request body
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReq.Namespace = client.Config.Namespace
+        // Get API request options
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.AccessToken = accesstoken
+        apiGetReqOptions.SpaceGuid = spaceguid
+
+        // List API request query parameters
+        apiListReqOptions := new(whisk.ApiListRequestOptions)
+        apiListReqOptions.Limit = flags.common.limit
+        apiListReqOptions.Skip = flags.common.skip
+        apiListReqOptions.AccessToken = accesstoken
+        apiListReqOptions.SpaceGuid = spaceguid
+
+        if (len(args) == 0) {
+            retApiList, _, err = client.Apis.ListV2(apiListReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.ListV2(%#v) error: %s\n", apiListReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.ListV2 returned: %#v (%+v)\n", retApiList, retApiList)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArrayV2)(retApiList)
+        } else {
+            // The first argument is either a basepath (must start with /) or an API name
+            apiGetReqOptions.ApiBasePath = args[0]
+            if (len(args) > 1) {
+                // Is the API path valid?
+                if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiRelPath = args[1]
+            }
+            if (len(args) > 2) {
+                // Is the API verb valid?
+                if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiVerb = strings.ToUpper(args[2])
+            }
+
+            retApi, _, err = client.Apis.GetV2(apiGetReq, apiGetReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.GetV2(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.GetV2 returned: %#v\n", retApi)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArrayV2)(retApi)
+        }
+
+        // Display the APIs - applying any specified filtering
+        if (flags.common.full) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} APIs\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                    }))
+
+            for i:=0; i<len(retApiArray.Apis); i++ {
+                printFilteredListApiV2(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions))
+            }
+        } else {
+            if (len(retApiArray.Apis) > 0) {
+                // Dynamically create the output format string based on the maximum size of the
+                // fully qualified action name and the API Name.
+                maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSizeV2(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+                maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSizeV2(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+                fmtString = "%-"+strconv.Itoa(maxActionNameSize)+"s %7s %"+strconv.Itoa(maxApiNameSize+1)+"s  %s\n"
+                fmt.Fprintf(color.Output,
+                    wski18n.T("{{.ok}} APIs\n",
+                        map[string]interface{}{
+                            "ok": color.GreenString("ok:"),
+                        }))
+                fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+                for i:=0; i<len(retApiArray.Apis); i++ {
+                    printFilteredListRowV2(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions), maxActionNameSize, maxApiNameSize)
+                }
+            } else {
+                fmt.Fprintf(color.Output,
+                    wski18n.T("{{.ok}} APIs\n",
+                        map[string]interface{}{
+                            "ok": color.GreenString("ok:"),
+                        }))
+                fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+            }
+        }
+
+        return nil
+    },
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API endpoint matching the filtering criteria, display
+ * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url)
+ */
+func printFilteredListApiV2(resultApi *whisk.RetApiV2, api *whisk.ApiOptions) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    basePath := resultApi.Swagger.BasePath
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: operation matches: %#v\n", opv)
+                        var actionName string
+                        if (len(opv.XOpenWhisk.Package) > 0) {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                        } else {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        }
+                        fmt.Printf("%s: %s\n", wski18n.T("Action"), actionName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("API Name"), apiName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Base path"), basePath)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Path"), path)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Verb"), op)
+                        fmt.Printf("  %s: %s\n", wski18n.T("URL"), baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API matching the filtering criteria, display the API
+ * on a single line (action name, verb, api name, api gw url).
+ *
+ * NOTE: Large action name and api name value will be truncated by their associated max size parameters.
+ */
+func printFilteredListRowV2(resultApi *whisk.RetApiV2, api *whisk.ApiOptions, maxActionNameSize int, maxApiNameSize int) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: operation matches: %#v\n", opv)
+                        var actionName string
+                        if (len(opv.XOpenWhisk.Package) > 0) {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                        } else {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        }
+                        fmt.Printf(fmtString,
+                            actionName[0 : min(len(actionName), maxActionNameSize)],
+                            op,
+                            apiName[0 : min(len(apiName), maxApiNameSize)],
+                            baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+func getLargestActionNameSizeV2(retApiArray *whisk.RetApiArrayV2, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            var fullActionName string
+                            if (len(opv.XOpenWhisk.Package) > 0) {
+                                fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                            } else {
+                                fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                            }
+                            if (len(fullActionName) > maxNameSize) {
+                                maxNameSize = len(fullActionName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+func getLargestApiNameSizeV2(retApiArray *whisk.RetApiArrayV2, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        apiName := resultApi.Swagger.Info.Title
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            if (len(apiName) > maxNameSize) {
+                                maxNameSize = len(apiName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+/*
+ * if # args = 4
+ * args[0] = API base path
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ *
+ * if # args = 3
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ */
+func parseApiV2(cmd *cobra.Command, args []string) (*whisk.Api, *QualifiedName, error) {
+    var err error
+    var basepath string = "/"
+    var apiname string
+    var basepathArgIsApiName = false;
+
+    api := new(whisk.Api)
+
+    if (len(args) > 3) {
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            basepathArgIsApiName = true;
+        }
+        basepath = args[0]
+
+        // Shift the args so the remaining code works with or without the explicit base path arg
+        args = args[1:]
+    }
+
+    // Is the API path valid?
+    if (len(args) > 0) {
+        if whiskErr, ok := isValidRelpath(args[0]); !ok {
+            return nil, nil, whiskErr
+        }
+        api.GatewayRelPath = args[0]    // Maintain case as URLs may be case-sensitive
+    }
+
+    // Is the API verb valid?
+    if (len(args) > 1) {
+        if whiskErr, ok := IsValidApiVerb(args[1]); !ok {
+            return nil, nil, whiskErr
+        }
+        api.GatewayMethod = strings.ToUpper(args[1])
+    }
+
+    // Is the specified action name valid?
+    var qName QualifiedName
+    if (len(args) == 3) {
+        qName = QualifiedName{}
+        qName, err = parseQualifiedName(args[2])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[2], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name: {{.err}}",
+                map[string]interface{}{"name": args[2], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+        if (qName.entityName == "") {
+            whisk.Debug(whisk.DbgError, "Action name '%s' is invalid\n", args[2])
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name.", map[string]interface{}{"name": args[2]})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+    }
+
+    if ( len(flags.api.apiname) > 0 ) {
+        if (basepathArgIsApiName) {
+            // Specifying API name as argument AND as a --apiname option value is invalid
+            whisk.Debug(whisk.DbgError, "API is specified as an argument '%s' and as a flag '%s'\n", basepath, flags.api.apiname)
+            errMsg := wski18n.T("An API name can only be specified once.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+        apiname = flags.api.apiname
+    }
+
+    api.Namespace = client.Config.Namespace
+    api.Action = new(whisk.ApiAction)
+    var urlActionPackage string
+    if (len(qName.packageName) > 0) {
+        urlActionPackage = qName.packageName
+    } else {
+        urlActionPackage = "default"
+    }
+    api.Action.BackendUrl = "https://" + client.Config.Host + "/api/v1/web/" + qName.namespace + "/" + urlActionPackage + "/" + qName.entity + ".http"
+    api.Action.BackendMethod = api.GatewayMethod
+    api.Action.Name = qName.entityName
+    api.Action.Namespace = qName.namespace
+    api.Action.Auth = client.Config.AuthToken
+    api.ApiName = apiname
+    api.GatewayBasePath = basepath
+    if (!basepathArgIsApiName) { api.Id = "API:"+api.Namespace+":"+api.GatewayBasePath }
+
+    whisk.Debug(whisk.DbgInfo, "Parsed api struct: %#v\n", api)
+    return api, &qName, nil
+}
+
+func parseSwaggerApiV2() (*whisk.Api, error) {
+    // Test is for completeness, but this situation should only arise due to an internal error
+    if ( len(flags.api.configfile) == 0 ) {
+        whisk.Debug(whisk.DbgError, "No swagger file is specified\n")
+        errMsg := wski18n.T("A configuration file was not specified.")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg),whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    swagger, err:= readFile(flags.api.configfile)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error reading swagger file '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    // Parse the JSON into a swagger object
+    swaggerObj := new(whisk.ApiSwaggerV2)
+    err = json.Unmarshal([]byte(swagger), swaggerObj)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "JSON parse of `%s' error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error parsing swagger file '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if (swaggerObj.BasePath == "" || swaggerObj.SwaggerName == "" || swaggerObj.Info == nil || swaggerObj.Paths == nil) {
+        whisk.Debug(whisk.DbgError, "Swagger file is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file is invalid (missing basePath, info, paths, or swagger fields)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if _, ok := isValidBasepath(swaggerObj.BasePath); !ok {
+        whisk.Debug(whisk.DbgError, "Swagger file basePath is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file basePath must start with a leading slash (/)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    api := new(whisk.Api)
+    api.Namespace = client.Config.Namespace
+    api.Swagger = swagger
+
+    return api, nil
+}
+
+///////////
+// Flags //
+///////////
+
+func init() {
+    apiCreateCmd.Flags().StringVarP(&flags.api.apiname, "apiname", "n", "", wski18n.T("Friendly name of the API; ignored when CFG_FILE is specified (default BASE_PATH)"))
+    apiCreateCmd.Flags().StringVarP(&flags.api.configfile, "config-file", "c", "", wski18n.T("`CFG_FILE` containing API configuration in swagger JSON format"))
+    //apiUpdateCmd.Flags().StringVarP(&flags.api.action, "action", "a", "", wski18n.T("`ACTION` to invoke when API is called"))
+    //apiUpdateCmd.Flags().StringVarP(&flags.api.path, "path", "p", "", wski18n.T("relative `PATH` of API"))
+    //apiUpdateCmd.Flags().StringVarP(&flags.api.verb, "method", "m", "", wski18n.T("API `VERB`"))
+    apiGetCmd.Flags().BoolVarP(&flags.common.detail, "full", "f", false, wski18n.T("display full API configuration details"))
+    apiListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
+    apiListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
+    apiListCmd.Flags().BoolVarP(&flags.common.full, "full", "f", false, wski18n.T("display full description of each API"))
+    apiExperimentalCmd.AddCommand(
+        apiCreateCmd,
+        //apiUpdateCmd,
+        apiGetCmd,
+        apiDeleteCmd,
+        apiListCmd,
+    )
+
+    apiCreateCmdV2.Flags().StringVarP(&flags.api.apiname, "apiname", "n", "", wski18n.T("Friendly name of the API; ignored when CFG_FILE is specified (default BASE_PATH)"))
+    apiCreateCmdV2.Flags().StringVarP(&flags.api.configfile, "config-file", "c", "", wski18n.T("`CFG_FILE` containing API configuration in swagger JSON format"))
+    apiCreateCmdV2.Flags().StringVar(&flags.api.resptype, "response-type", "json", wski18n.T("Set the web action response `TYPE`. Possible values are html, http, json, text, svg"))
+    apiGetCmdV2.Flags().BoolVarP(&flags.common.detail, "full", "f", false, wski18n.T("display full API configuration details"))
+    apiListCmdV2.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
+    apiListCmdV2.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
+    apiListCmdV2.Flags().BoolVarP(&flags.common.full, "full", "f", false, wski18n.T("display full description of each API"))
+    apiCmd.AddCommand(
+        apiCreateCmdV2,
+        apiGetCmdV2,
+        apiDeleteCmdV2,
+        apiListCmdV2,
+    )
+}
diff --git a/commands/commands.go b/commands/commands.go
index 133dc37..30947f7 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -1,47 +1,214 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"fmt"
-	"net/http"
-	"net/url"
-	"os"
+    "errors"
+    "fmt"
+    "net/http"
+    "os"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
+
+    "github.com/spf13/cobra"
 )
 
 var client *whisk.Client
+const DefaultOpenWhiskApiPath string = "/api"
+
+func setupClientConfig(cmd *cobra.Command, args []string) (error){
+    baseURL, err := getURLBase(Properties.APIHost, DefaultOpenWhiskApiPath)
+
+    // Determine if the parent command will require the API host to be set
+    apiHostRequired := (cmd.Parent().Name() == "property" && cmd.Name() == "get" && (flags.property.auth ||
+      flags.property.apihost || flags.property.namespace || flags.property.apiversion || flags.property.cliversion)) ||
+      (cmd.Parent().Name() == "property" && cmd.Name() == "set" && (len(flags.property.apihostSet) > 0 ||
+        len(flags.property.apiversionSet) > 0 || len(flags.global.auth) > 0)) ||
+      (cmd.Parent().Name() == "sdk" && cmd.Name() == "install" && len(args) > 0 && args[0] == "bashauto")
+
+    // Display an error if the parent command requires an API host to be set, and the current API host is not valid
+    if err != nil && !apiHostRequired {
+        whisk.Debug(whisk.DbgError, "getURLBase(%s, %s) error: %s\n", Properties.APIHost, DefaultOpenWhiskApiPath, err)
+        errMsg := wski18n.T("The API host is not valid: {{.err}}", map[string]interface{}{"err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return whiskErr
+    }
+
+    clientConfig := &whisk.Config{
+        AuthToken:  Properties.Auth,
+        Namespace:  Properties.Namespace,
+        BaseURL:    baseURL,
+        Version:    Properties.APIVersion,
+        Insecure:   flags.global.insecure,
+        Host:       Properties.APIHost,
+    }
+
+    // Setup client
+    client, err = whisk.NewClient(http.DefaultClient, clientConfig)
+
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "whisk.NewClient(%#v, %#v) error: %s\n", http.DefaultClient, clientConfig, err)
+        errMsg := wski18n.T("Unable to initialize server connection: {{.err}}", map[string]interface{}{"err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr
+    }
+
+    return nil
+}
 
 func init() {
-	var err error
+    var err error
 
-	err = loadProperties()
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(-1)
-	}
+    err = loadProperties()
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "loadProperties() error: %s\n", err)
+        fmt.Println(err)
+        os.Exit(whisk.EXITCODE_ERR_GENERAL)
+    }
+}
 
-	baseURL, err := url.Parse(Properties.APIHost)
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(-1)
-	}
+func getKeyValueArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) {
+    var whiskErr error
+    var key string
+    var value string
 
-	clientConfig := &whisk.Config{
-		AuthToken: Properties.Auth,
-		Namespace: Properties.Namespace,
-		BaseURL:   baseURL,
-		Version:   Properties.APIVersion,
-	}
+    if len(args) - 1 >= argIndex + 2 {
+        key = args[argIndex + 1]
+        value = args[argIndex + 2]
+        parsedArgs = append(parsedArgs, getFormattedJSON(key, value))
+        args = append(args[:argIndex], args[argIndex + 3:]...)
+    } else {
+        whisk.Debug(whisk.DbgError, "Arguments for '%s' must be a key/value pair; args: %s", args[argIndex], args)
+        errMsg := wski18n.T("Arguments for '{{.arg}}' must be a key/value pair",
+            map[string]interface{}{"arg": args[argIndex]})
+        whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+            whisk.DISPLAY_USAGE)
+    }
 
-	// Setup client
-	client, err = whisk.NewClient(http.DefaultClient, clientConfig)
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(-1)
-	}
+    return parsedArgs, args, whiskErr
+}
 
+func getValueFromArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) {
+    var whiskErr error
+
+    if len(args) - 1 >= argIndex + 1 {
+        parsedArgs = append(parsedArgs, args[argIndex + 1])
+        args = append(args[:argIndex], args[argIndex + 2:]...)
+    } else {
+        whisk.Debug(whisk.DbgError, "An argument must be provided for '%s'; args: %s", args[argIndex], args)
+        errMsg := wski18n.T("An argument must be provided for '{{.arg}}'",
+            map[string]interface{}{"arg": args[argIndex]})
+        whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+            whisk.DISPLAY_USAGE)
+    }
+
+    return parsedArgs, args, whiskErr
+}
+
+func parseArgs(args []string) ([]string, []string, []string, error) {
+    var paramArgs []string
+    var annotArgs []string
+    var whiskErr error
+
+    i := 0
+
+    for i < len(args) {
+        if args[i] == "-P" || args[i] == "--param-file" {
+            paramArgs, args, whiskErr = getValueFromArgs(args, i, paramArgs)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
+                errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}",
+                    map[string]interface{}{"err": whiskErr})
+                whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+                    whisk.DISPLAY_USAGE)
+                return nil, nil, nil, whiskErr
+            }
+
+            filename := paramArgs[len(paramArgs) - 1]
+            paramArgs[len(paramArgs) - 1], whiskErr = readFile(filename)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr)
+                return nil, nil, nil, whiskErr
+            }
+        } else if args[i] == "-A" || args[i] == "--annotation-file" {
+            annotArgs, args, whiskErr = getValueFromArgs(args, i, annotArgs)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
+                errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}",
+                    map[string]interface{}{"err": whiskErr})
+                whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+                    whisk.DISPLAY_USAGE)
+                return nil, nil, nil, whiskErr
+            }
+
+            filename := annotArgs[len(annotArgs) - 1]
+            annotArgs[len(annotArgs) - 1], whiskErr = readFile(filename)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr)
+                return nil, nil, nil, whiskErr
+            }
+        } else if args[i] == "-p" || args[i] == "--param" {
+            paramArgs, args, whiskErr = getKeyValueArgs(args, i, paramArgs)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
+                errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}",
+                    map[string]interface{}{"err": whiskErr})
+                whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+                    whisk.DISPLAY_USAGE)
+                return nil, nil, nil, whiskErr
+            }
+        } else if args[i] == "-a" || args[i] == "--annotation"{
+            annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs)
+            if whiskErr != nil {
+                whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
+                errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}",
+                    map[string]interface{}{"err": whiskErr})
+                whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+                    whisk.DISPLAY_USAGE)
+                return nil, nil, nil, whiskErr
+            }
+        } else {
+            i++
+        }
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Found param args '%s'.\n", paramArgs)
+    whisk.Debug(whisk.DbgInfo, "Found annotations args '%s'.\n", annotArgs)
+    whisk.Debug(whisk.DbgInfo, "Arguments with param args removed '%s'.\n", args)
+
+    return args, paramArgs, annotArgs, nil
 }
 
 func Execute() error {
-	return WskCmd.Execute()
+    var err error
+
+    whisk.Debug(whisk.DbgInfo, "wsk args: %#v\n", os.Args)
+    os.Args, flags.common.param, flags.common.annotation, err = parseArgs(os.Args)
+
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "parseParams(%s) failed: %s\n", os.Args, err)
+        errMsg := wski18n.T("Failed to parse arguments: {{.err}}", map[string]interface{}{"err":err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr
+    }
+
+    return WskCmd.Execute()
 }
diff --git a/commands/flags.go b/commands/flags.go
index 5b30078..e48ac93 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -1,73 +1,130 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
+import (
+    "os"
+)
+
 ///////////
 // Flags //
 ///////////
 
+const MEMORY_FLAG   = "memory"
+const LOG_SIZE_FLAG = "logsize"
+const TIMEOUT_FLAG  = "timeout"
+const WEB_FLAG      = "web"
+
+var cliDebug = os.Getenv("WSK_CLI_DEBUG")  // Useful for tracing init() code
+
 var flags struct {
-	global struct {
-		verbose    bool
-		auth       string
-		apihost    string
-		apiversion string
-	}
 
-	common struct {
-		blocking   bool
-		annotation []string
-		param      []string
-		shared     bool // AKA "public" or "publish"
-		skip       int  // skip first N records
-		limit      int  // return max N records
-		full       bool // return full records (docs=true for client request)
-		summary    bool
-	}
+    global struct {
+        verbose     bool
+        debug       bool
+        auth        string
+        apihost     string
+        apiversion  string
+        insecure    bool
+    }
 
-	property struct {
-		auth          bool
-		apihost       bool
-		apiversion    bool
-		namespace     bool
-		cliversion    bool
-		apibuild      bool
-		all           bool
-		apihostSet    string
-		apiversionSet string
-		namespaceSet  string
-	}
+    common struct {
+        blocking    bool
+        annotation  []string
+        annotFile   string
+        param       []string
+        paramFile   string
+        shared      string // AKA "public" or "publish"
+        skip        int  // skip first N records
+        limit       int  // return max N records
+        full        bool // return full records (docs=true for client request)
+        summary     bool
+        feed        string  // name of feed
+        detail      bool
+    }
 
-	action struct {
-		docker   bool
-		copy     bool
-		pipe     bool
-		shared   bool
-		sequence bool
-		lib      string
-		timeout  int
-		memory   int
-		result   bool
-		xPackage string
-	}
+    property struct {
+        auth            bool
+        apihost         bool
+        apiversion      bool
+        namespace       bool
+        cliversion      bool
+        apibuild        bool
+        apibuildno      bool
+        insecure        bool
+        all             bool
+        apihostSet      string
+        apiversionSet   string
+        namespaceSet    string
+    }
 
-	activation struct {
-		action       string // retrieve results for this action
-		upto         int64  // retrieve results up to certain time
-		since        int64  // retrieve results after certain time
-		seconds      int    // stop polling for activation upda
-		sinceSeconds int
-		sinceMinutes int
-		sinceHours   int
-		sinceDays    int
-		exit         int
-	}
+    action struct {
+        docker      bool
+        copy        bool
+        pipe        bool
+        web         string
+        sequence    bool
+        timeout     int
+        memory      int
+        logsize     int
+        result      bool
+        kind        string
+        main        string
+    }
 
-	xPackage struct {
-		serviceGUID string
-	}
+    activation struct {
+        action          string // retrieve results for this action
+        upto            int64  // retrieve results up to certain time
+        since           int64  // retrieve results after certain time
+        seconds         int    // stop polling for activation upda
+        sinceSeconds    int
+        sinceMinutes    int
+        sinceHours      int
+        sinceDays       int
+        exit            int
+    }
 
-	// rule
-	rule struct {
-		enable  bool
-		disable bool
-	}
+    // rule
+    rule struct {
+        disable bool
+        summary bool
+    }
+
+    // trigger
+    trigger struct {
+        summary bool
+    }
+
+    // api
+    api struct {
+        action     string
+        path       string
+        verb       string
+        basepath   string
+        apiname    string
+        configfile string
+        resptype   string
+    }
+}
+
+func IsVerbose() bool {
+    return flags.global.verbose || IsDebug()
+}
+
+func IsDebug() bool {
+    return len(cliDebug) > 0 || flags.global.debug
 }
diff --git a/commands/namespace.go b/commands/namespace.go
index e552a44..613c7ec 100644
--- a/commands/namespace.go
+++ b/commands/namespace.go
@@ -1,68 +1,126 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"fmt"
+    "fmt"
+    "errors"
 
-	"github.com/spf13/cobra"
+    "github.com/spf13/cobra"
+    "github.com/fatih/color"
+
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 )
 
-// ruleCmd represents the rule command
+// namespaceCmd represents the namespace command
 var namespaceCmd = &cobra.Command{
-	Use:   "namespace",
-	Short: "work with namespaces",
+    Use:   "namespace",
+    Short: wski18n.T("work with namespaces"),
 }
 
 var namespaceListCmd = &cobra.Command{
-	Use:   "list",
-	Short: "list available namespaces",
+    Use:   "list",
+    Short: wski18n.T("list available namespaces"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        // add "TYPE" --> public / private
 
-	Run: func(cmd *cobra.Command, args []string) {
-		// add "TYPE" --> public / private
+        if whiskErr := checkArgs(args, 0, 0, "Namespace list", wski18n.T("No arguments are required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		namespaces, _, err := client.Namespaces.List()
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		printList(namespaces)
-	},
+        namespaces, _, err := client.Namespaces.List()
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Namespaces.List() error: %s\n", err)
+            errStr := wski18n.T("Unable to obtain the list of available namespaces: {{.err}}",
+                map[string]interface{}{"err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_NETWORK, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+        printList(namespaces)
+        return nil
+    },
 }
 
 var namespaceGetCmd = &cobra.Command{
-	Use:   "get <namespace string>",
-	Short: "get triggers, actions, and rules in the registry for a namespace",
+    Use:   "get [NAMESPACE]",
+    Short: wski18n.T("get triggers, actions, and rules in the registry for a namespace"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var qName QualifiedName
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var nsName string
-		if len(args) > 0 {
-			nsName = args[0]
-		}
+        if whiskErr := checkArgs(args, 0, 1, "Namespace get",
+                wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		namespace, _, err := client.Namespaces.Get(nsName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        // Namespace argument is optional; defaults to configured property namespace
+        if len(args) == 1 {
+            qName, err = parseQualifiedName(args[0])
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+                errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                        map[string]interface{}{"name": args[0], "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
 
-		fmt.Printf("entities in namespace: %s\n", boldString(namespace.Name))
-		printList(namespace.Contents.Packages)
-		printList(namespace.Contents.Actions)
-		printList(namespace.Contents.Triggers)
-		printList(namespace.Contents.Rules)
+        namespace, _, err := client.Namespaces.Get(qName.namespace)
 
-	},
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Namespaces.Get(%s) error: %s\n", getClientNamespace(), err)
+            errStr := wski18n.T("Unable to obtain the list of entities for namespace '{{.namespace}}': {{.err}}",
+                    map[string]interface{}{"namespace": getClientNamespace(), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_NETWORK,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output, wski18n.T("Entities in namespace: {{.namespace}}\n",
+            map[string]interface{}{"namespace": boldString(getClientNamespace())}))
+        printList(namespace.Contents.Packages)
+        printList(namespace.Contents.Actions)
+        printList(namespace.Contents.Triggers)
+        printList(namespace.Contents.Rules)
+
+        return nil
+    },
 }
 
-// listCmd is a shortcut for "wsk namespace get _"
 var listCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list triggers, actions, and rules in the registry for a namespace",
-	Run:   namespaceGetCmd.Run,
+    Use:   "list",
+    Short: wski18n.T("list entities in the current namespace"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE:   namespaceGetCmd.RunE,
 }
 
 func init() {
-	namespaceCmd.AddCommand(
-		namespaceListCmd,
-		namespaceGetCmd,
-	)
+    namespaceCmd.AddCommand(
+        namespaceListCmd,
+        namespaceGetCmd,
+    )
 }
diff --git a/commands/package.go b/commands/package.go
index 5d6a310..939eff5 100644
--- a/commands/package.go
+++ b/commands/package.go
@@ -1,353 +1,581 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"errors"
-	"fmt"
-	"net/http"
+  "errors"
+  "fmt"
+  "net/http"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+  "github.com/openwhisk/openwhisk-client-go/whisk"
+  "github.com/openwhisk/openwhisk-cli/wski18n"
 
-	"github.com/fatih/color"
-	"github.com/spf13/cobra"
+  "github.com/fatih/color"
+  "github.com/spf13/cobra"
 )
 
 var packageCmd = &cobra.Command{
-	Use:   "package",
-	Short: "work with packages",
+  Use:   "package",
+  Short: wski18n.T("work with packages"),
 }
 
 var packageBindCmd = &cobra.Command{
-	Use:   "bind <package string> <name string>",
-	Short: "bind parameters to the package",
+  Use:           "bind PACKAGE_NAME BOUND_PACKAGE_NAME",
+  Short:         wski18n.T("bind parameters to a package"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		fmt.Println("TODO :: this command has been commented out because it is out of date")
+    if whiskErr := checkArgs(args, 2, 2, "Package bind",
+            wski18n.T("A package name and binding name are required.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		// var err error
-		// if len(args) != 2 {
-		// 	err = errors.New("Invalid argument list")
-		// 	fmt.Println(err)
-		// 	return
-		// }
-		//
-		// bindingArg := args[0]
-		// packageName := args[1]
-		//
-		// parameters, err := parseParameters(flags.common.param)
-		// if err != nil {
-		// 	fmt.Println(err)
-		// 	return
-		// }
-		//
-		// annotations, err := parseAnnotations(flags.common.annotation)
-		// if err != nil {
-		// 	fmt.Println(err)
-		// 	return
-		// }
-		//
-		// parsedBindingArg := strings.Split(bindingArg, ":")
-		// bindingName := parsedBindingArg[0]
-		// var bindingNamespace string
-		// if len(parsedBindingArg) == 1 {
-		// 	bindingNamespace = client.Config.Namespace
-		// } else if len(parsedBindingArg) == 2 {
-		// 	bindingNamespace = parsedBindingArg[1]
-		// } else {
-		// 	err = fmt.Errorf("Invalid binding argument %s", bindingArg)
-		// 	fmt.Println(err)
-		// 	return
-		// }
-		//
-		// binding := whisk.Binding{
-		// 	Name:      bindingName,
-		// 	Namespace: bindingNamespace,
-		// }
-		//
-		// p := &whisk.Package{
-		// 	Name:        packageName,
-		// 	Publish:     flags.common.shared,
-		// 	Annotations: annotations,
-		// 	Parameters:  parameters,
-		// 	Binding:     binding,
-		// }
-		// p, _, err = client.Packages.Insert(p, false)
-		// if err != nil {
-		// 	fmt.Println(err)
-		// 	return
-		// }
-		//
-		// printJSON(p)
-	},
+    packageName := args[0]
+    pkgQName, err := parseQualifiedName(packageName)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", packageName, err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": packageName, "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    bindingName := args[1]
+    bindQName, err := parseQualifiedName(bindingName)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", bindingName, err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": bindingName, "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    client.Namespace = bindQName.namespace
+
+    // Convert the binding's list of default parameters from a string into []KeyValue
+    // The 1 or more --param arguments have all been combined into a single []string
+    // e.g.   --p arg1,arg2 --p arg3,arg4   ->  [arg1, arg2, arg3, arg4]
+
+    whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", flags.common.param)
+    parameters, err := getJSONFromStrings(flags.common.param, true)
+
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.param, err)
+      errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+          map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
+
+    // Convert the binding's list of default annotations from a string into []KeyValue
+    // The 1 or more --annotation arguments have all been combined into a single []string
+    // e.g.   --a arg1,arg2 --a arg3,arg4   ->  [arg1, arg2, arg3, arg4]
+    whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", flags.common.annotation)
+    annotations, err := getJSONFromStrings(flags.common.annotation, true)
+
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.annotation, err)
+      errStr := wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+          map[string]interface{}{"annotation": fmt.Sprintf("%#v",flags.common.annotation), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
+
+    binding := whisk.Binding{
+      Name:      pkgQName.entityName,
+      Namespace: pkgQName.namespace,
+    }
+
+    p := &whisk.BindingPackage{
+      Name:        bindQName.entityName,
+      Annotations: annotations.(whisk.KeyValueArr),
+      Parameters:  parameters.(whisk.KeyValueArr),
+      Binding:     binding,
+    }
+
+    _, _, err = client.Packages.Insert(p, false)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Insert(%#v, false) failed: %s\n", p, err)
+      errStr := wski18n.T("Binding creation failed: {{.err}}", map[string]interface{}{"err":err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    fmt.Fprintf(color.Output, wski18n.T("{{.ok}} created binding {{.name}}\n",
+      map[string]interface{}{"ok": color.GreenString(wski18n.T("ok:")), "name":boldString(bindingName)}))
+    return nil
+  },
 }
 
 var packageCreateCmd = &cobra.Command{
-	Use:   "create <name string>",
-	Short: "create a new package",
+  Use:           "create PACKAGE_NAME",
+  Short:         wski18n.T("create a new package"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
+    var shared, sharedSet bool
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+    if whiskErr := checkArgs(args, 1, 1, "Package create", wski18n.T("A package name is required.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		packageName := args[0]
+    qName, err := parseQualifiedName(args[0])
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": args[0], "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+    client.Namespace = qName.namespace
 
-		parameters, err := parseParameters(flags.common.param)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    if shared, sharedSet, err = parseShared(flags.common.shared); err != nil {
+      whisk.Debug(whisk.DbgError, "parseShared(%s) failed: %s\n", flags.common.shared, err)
+      return err
+    }
 
-		annotations, err := parseAnnotations(flags.common.annotation)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", flags.common.param)
+    parameters, err := getJSONFromStrings(flags.common.param, true)
 
-		p := &whisk.Package{
-			Name:        packageName,
-			Publish:     flags.common.shared,
-			Annotations: annotations,
-			Parameters:  parameters,
-		}
-		p, _, err = client.Packages.Insert(p, false)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.param, err)
+      errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+          map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
 
-		fmt.Printf("%s created package %s\n", color.GreenString("ok:"), boldString(p.Name))
-	},
+    whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", flags.common.annotation)
+    annotations, err := getJSONFromStrings(flags.common.annotation, true)
+
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.annotation, err)
+      errStr := wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+          map[string]interface{}{"annotation": fmt.Sprintf("%#v",flags.common.annotation), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
+
+    p := &whisk.Package{
+      Name:        qName.entityName,
+      Namespace:   qName.namespace,
+      Annotations: annotations.(whisk.KeyValueArr),
+      Parameters:  parameters.(whisk.KeyValueArr),
+    }
+
+    if sharedSet {
+      p.Publish = &shared
+    }
+
+    p, _, err = client.Packages.Insert(p, false)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Insert(%#v, false) failed: %s\n", p, err)
+      errStr := wski18n.T(
+        "Unable to create package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err": err,
+        })
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    fmt.Fprintf(color.Output, wski18n.T("{{.ok}} created package {{.name}}\n",
+      map[string]interface{}{"ok": color.GreenString(wski18n.T("ok:")), "name":boldString(qName.entityName)}))
+    return nil
+  },
 }
 
 var packageUpdateCmd = &cobra.Command{
-	Use:   "update <name string>",
-	Short: "update an existing package",
+  Use:           "update PACKAGE_NAME",
+  Short:         wski18n.T("update an existing package, or create a package if it does not exist"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
+    var shared, sharedSet bool
 
-	Run: func(cmd *cobra.Command, args []string) {
-		// TODO :: parse annotations
-		// TODO ::parse parameters
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+    if whiskErr := checkArgs(args, 1, 1, "Package update", wski18n.T("A package name is required.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		packageName := args[0]
+    qName, err := parseQualifiedName(args[0])
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": args[0], "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+    client.Namespace = qName.namespace
 
-		parameters, err := parseParameters(flags.common.param)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    if shared, sharedSet, err = parseShared(flags.common.shared); err != nil {
+      whisk.Debug(whisk.DbgError, "parseShared(%s) failed: %s\n", flags.common.shared, err)
+      return err
+    }
 
-		annotations, err := parseAnnotations(flags.common.annotation)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", flags.common.param)
+    parameters, err := getJSONFromStrings(flags.common.param, true)
 
-		p := &whisk.Package{
-			Name:        packageName,
-			Publish:     flags.common.shared,
-			Annotations: annotations,
-			Parameters:  parameters,
-		}
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.param, err)
+      errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+          map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
 
-		p, _, err = client.Packages.Insert(p, true)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", flags.common.annotation)
+    annotations, err := getJSONFromStrings(flags.common.annotation, true)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.annotation, err)
+      errStr := wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+          map[string]interface{}{"annotation": fmt.Sprintf("%#v",flags.common.annotation), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+      return werr
+    }
 
-		fmt.Printf("%s updated package %s\n", color.GreenString("ok:"), boldString(p.Name))
+    p := &whisk.Package{
+      Name:        qName.entityName,
+      Namespace:   qName.namespace,
+      Annotations: annotations.(whisk.KeyValueArr),
+      Parameters:  parameters.(whisk.KeyValueArr),
+    }
 
-	},
+    if sharedSet {
+      p.Publish = &shared
+    }
+
+    p, _, err = client.Packages.Insert(p, true)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Insert(%#v, true) failed: %s\n", p, err)
+      errStr := wski18n.T("Package update failed: {{.err}}", map[string]interface{}{"err":err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    fmt.Fprintf(color.Output, wski18n.T("{{.ok}} updated package {{.name}}\n",
+      map[string]interface{}{"ok": color.GreenString(wski18n.T("ok:")), "name":boldString(qName.entityName)}))
+    return nil
+  },
 }
 
 var packageGetCmd = &cobra.Command{
-	Use:   "get <name string>",
-	Short: "get package",
+  Use:           "get PACKAGE_NAME [FIELD_FILTER]",
+  Short:         wski18n.T("get package"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
+    var field string
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+    if whiskErr := checkArgs(args, 1, 2, "Package get", wski18n.T("A package name is required.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		packageName := args[0]
+    if len(args) > 1 {
+      field = args[1]
 
-		xPackage, _, err := client.Packages.Get(packageName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+      if !fieldExists(&whisk.Package{}, field) {
+        errMsg := wski18n.T("Invalid field filter '{{.arg}}'.", map[string]interface{}{"arg": field})
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+          whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return whiskErr
+      }
+    }
 
-		if flags.common.summary {
-			fmt.Printf("%s /%s/%s\n", boldString("package"), xPackage.Namespace, xPackage.Name)
-		} else {
-			fmt.Printf("%s got package %s\n", color.GreenString("ok:"), boldString(packageName))
-			printJSON(xPackage)
-		}
-	},
+    qName, err := parseQualifiedName(args[0])
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": args[0], "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+    client.Namespace = qName.namespace
+
+    xPackage, _, err := client.Packages.Get(qName.entityName)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Get(%s) failed: %s\n", qName.entityName, err)
+      errStr := wski18n.T(
+        "Unable to get package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err":err,
+        })
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    if flags.common.summary {
+      printSummary(xPackage)
+    } else {
+
+      if len(field) > 0 {
+        fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got package {{.name}}, displaying field {{.field}}\n",
+          map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName),
+          "field": boldString(field)}))
+        printField(xPackage, field)
+      } else {
+        fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got package {{.name}}\n",
+          map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName)}))
+        printJSON(xPackage)
+      }
+    }
+
+    return nil
+  },
 }
 
 var packageDeleteCmd = &cobra.Command{
-	Use:   "delete <name string>",
-	Short: "delete package",
+  Use:           "delete PACKAGE_NAME",
+  Short:         wski18n.T("delete package"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+    if whiskErr := checkArgs(args, 1, 1, "Package delete", wski18n.T("A package name is required.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		packageName := args[0]
+    qName, err := parseQualifiedName(args[0])
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+      errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+          map[string]interface{}{"name": args[0], "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+        whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+    client.Namespace = qName.namespace
 
-		_, err = client.Packages.Delete(packageName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    _, err = client.Packages.Delete(qName.entityName)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Delete(%s) failed: %s\n", qName.entityName, err)
+      errStr := wski18n.T(
+        "Unable to delete package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err": err,
+        })
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
 
-		fmt.Printf("%s deleted package %s\n", color.GreenString("ok:"), boldString(packageName))
-	},
+    fmt.Fprintf(color.Output,
+      wski18n.T("{{.ok}} deleted package {{.name}}\n",
+        map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName)}))
+    return nil
+  },
 }
 
 var packageListCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list all packages",
+  Use:           "list [NAMESPACE]",
+  Short:         wski18n.T("list all packages"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
+    var shared bool
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		qName := qualifiedName{}
-		if len(args) == 1 {
-			qName, err = parseQualifiedName(args[0])
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
-			ns := qName.namespace
-			if len(ns) == 0 {
-				err = errors.New("No valid namespace detected.  Make sure that namespace argument is preceded by a \"/\"")
-				fmt.Printf("error: %s\n", err)
-				return
-			}
+    qName := QualifiedName{}
+    if len(args) == 1 {
+      qName, err = parseQualifiedName(args[0])
+      if err != nil {
+        whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+        errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+            map[string]interface{}{"name": args[0], "err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+          whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+      }
+      ns := qName.namespace
+      if len(ns) == 0 {
+        whisk.Debug(whisk.DbgError, "An empty namespace in the package name '%s' is invalid \n", args[0])
+        errStr := wski18n.T("No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\"")
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return werr
+      }
 
-			client.Namespace = ns
-		}
+      client.Namespace = ns
+    } else if whiskErr := checkArgs(args, 0, 1, "Package list",
+        wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+      return whiskErr
+    }
 
-		options := &whisk.PackageListOptions{
-			Skip:   flags.common.skip,
-			Limit:  flags.common.limit,
-			Public: flags.common.shared,
-			Docs:   flags.common.full,
-		}
+    if flags.common.shared == "yes" {
+      shared = true
+    } else {
+      shared = false
+    }
 
-		packages, _, err := client.Packages.List(options)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    options := &whisk.PackageListOptions{
+      Skip:   flags.common.skip,
+      Limit:  flags.common.limit,
+      Public: shared,
+    }
 
-		printList(packages)
-	},
+    packages, _, err := client.Packages.List(options)
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.List(%+v) failed: %s\n", options, err)
+      errStr := wski18n.T("Unable to obtain the list of packages for namespace '{{.name}}': {{.err}}",
+          map[string]interface{}{"name": getClientNamespace(), "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    printList(packages)
+    return nil
+  },
 }
 
 var packageRefreshCmd = &cobra.Command{
-	Use:   "refresh <namespace string>",
-	Short: "refresh package bindings",
+  Use:           "refresh [NAMESPACE]",
+  Short:         wski18n.T("refresh package bindings"),
+  SilenceUsage:  true,
+  SilenceErrors: true,
+  PreRunE:       setupClientConfig,
+  RunE: func(cmd *cobra.Command, args []string) error {
+    var err error
+    var qName QualifiedName
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
+    if whiskErr := checkArgs(args, 0, 1, "Package refresh",
+        wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+      return whiskErr
+    } else {
+      if len(args) == 0 {
+        qName.namespace = getNamespace()
+      } else {
+        qName, err = parseQualifiedName(args[0])
 
-		if len(args) == 1 {
-			namespace := args[0]
-			currentNamespace := client.Config.Namespace
-			client.Config.Namespace = namespace
-			defer func() {
-				client.Config.Namespace = currentNamespace
-			}()
-		}
+        if err != nil {
+          whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+          errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+              map[string]interface{}{"name": args[0], "err": err})
+          werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+          return werr
+        }
+      }
+    }
 
-		updates, resp, err := client.Packages.Refresh()
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    currentNamespace := client.Config.Namespace
+    client.Config.Namespace = qName.namespace
 
-		switch resp.StatusCode {
-		case http.StatusOK:
-			fmt.Printf("\n%s refreshed successfully\n", client.Config.Namespace)
+    defer func() {
+      client.Config.Namespace = currentNamespace
+    }()
 
-			if len(updates.Added) > 0 {
-				fmt.Println("created bindings:")
-				printJSON(updates.Added)
-			} else {
-				fmt.Println("no bindings created")
-			}
+    updates, resp, err := client.Packages.Refresh()
+    if err != nil {
+      whisk.Debug(whisk.DbgError, "client.Packages.Refresh() of namespace '%s' failed: %s\n", client.Config.Namespace, err)
+      errStr := wski18n.T("Package refresh for namespace '{{.name}}' failed: {{.err}}",
+          map[string]interface{}{"name": client.Config.Namespace, "err": err})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+    whisk.Debug(whisk.DbgInfo, "Refresh updates received: %#v\n", updates)
 
-			if len(updates.Updated) > 0 {
-				fmt.Println("updated bindings:")
-				printJSON(updates.Updated)
-			} else {
-				fmt.Println("no bindings updated")
-			}
+    switch resp.StatusCode {
+    case http.StatusOK:
+      fmt.Printf(wski18n.T("{{.name}} refreshed successfully\n",
+        map[string]interface{}{"name": client.Config.Namespace}))
 
-			if len(updates.Deleted) > 0 {
-				fmt.Println("deleted bindings:")
-				printJSON(updates.Deleted)
-			} else {
-				fmt.Println("no bindings deleted")
-			}
+      fmt.Println(wski18n.T("created bindings:"))
 
-		case http.StatusNotImplemented:
-			fmt.Println("error: This feature is not implemented in the targeted deployment")
-			return
-		default:
-			fmt.Println("error: ", resp.Status)
-			return
-		}
+      if len(updates.Added) > 0 {
+        printArrayContents(updates.Added)
+      }
 
-	},
+      fmt.Println(wski18n.T("updated bindings:"))
+
+      if len(updates.Updated) > 0 {
+        printArrayContents(updates.Updated)
+      }
+
+      fmt.Println(wski18n.T("deleted bindings:"))
+
+      if len(updates.Deleted) > 0 {
+        printArrayContents(updates.Deleted)
+      }
+
+    case http.StatusNotImplemented:
+      whisk.Debug(whisk.DbgError, "client.Packages.Refresh() for namespace '%s' returned 'Not Implemented' HTTP status code: %d\n", client.Config.Namespace, resp.StatusCode)
+      errStr := wski18n.T("The package refresh feature is not implemented in the target deployment")
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_NETWORK, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    default:
+      whisk.Debug(whisk.DbgError, "client.Packages.Refresh() for namespace '%s' returned an unexpected HTTP status code: %d\n", client.Config.Namespace, resp.StatusCode)
+      errStr := wski18n.T("Package refresh for namespace '{{.name}}' failed due to unexpected HTTP status code: {{.code}}",
+          map[string]interface{}{"name": client.Config.Namespace, "code": resp.StatusCode})
+      werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_NETWORK, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+      return werr
+    }
+
+    return nil
+  },
 }
 
 func init() {
+  packageCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+  packageCreateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+  packageCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+  packageCreateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+  packageCreateCmd.Flags().StringVar(&flags.common.shared, "shared", "", wski18n.T("package visibility `SCOPE`; yes = shared, no = private"))
 
-	packageCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	packageCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
-	packageCreateCmd.Flags().StringVarP(&flags.xPackage.serviceGUID, "service_guid", "s", "", "a unique identifier of the service")
-	packageCreateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
+  packageUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+  packageUpdateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+  packageUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+  packageUpdateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+  packageUpdateCmd.Flags().StringVar(&flags.common.shared, "shared", "", wski18n.T("package visibility `SCOPE`; yes = shared, no = private"))
 
-	packageUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	packageUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
-	packageUpdateCmd.Flags().StringVarP(&flags.xPackage.serviceGUID, "service_guid", "s", "", "a unique identifier of the service")
-	packageUpdateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
+  packageGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, wski18n.T("summarize package details"))
 
-	packageGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, "summarize entity details")
+  packageBindCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+  packageBindCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+  packageBindCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+  packageBindCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
 
-	packageBindCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	packageBindCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
+  packageListCmd.Flags().StringVar(&flags.common.shared, "shared", "", wski18n.T("include publicly shared entities in the result"))
+  packageListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of packages from the result"))
+  packageListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of packages from the collection"))
 
-	packageListCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "include publicly shared entities in the result")
-	packageListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, "skip this many entities from the head of the collection")
-	packageListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 0, "only return this many entities from the collection")
-	packageListCmd.Flags().BoolVar(&flags.common.full, "full", false, "include full entity description")
-
-	packageCmd.AddCommand(
-		packageBindCmd,
-		packageCreateCmd,
-		packageUpdateCmd,
-		packageGetCmd,
-		packageDeleteCmd,
-		packageListCmd,
-		packageRefreshCmd,
-	)
+  packageCmd.AddCommand(
+    packageBindCmd,
+    packageCreateCmd,
+    packageUpdateCmd,
+    packageGetCmd,
+    packageDeleteCmd,
+    packageListCmd,
+    packageRefreshCmd,
+  )
 }
diff --git a/commands/property.go b/commands/property.go
index 38a2ee5..ed6b49e 100644
--- a/commands/property.go
+++ b/commands/property.go
@@ -1,335 +1,501 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"bufio"
-	"fmt"
-	"net/url"
-	"os"
-	"strings"
+    "errors"
+    "fmt"
+    "os"
 
-	"github.com/mitchellh/go-homedir"
-	"github.com/spf13/cobra"
+    "github.com/mitchellh/go-homedir"
+    "github.com/spf13/cobra"
+    "github.com/fatih/color"
+
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 )
 
 var Properties struct {
-	Auth       string
-	APIHost    string
-	APIVersion string
-	APIBuild   string
-	CLIVersion string
-	Namespace  string
-	PropsFile  string
+    Auth       string
+    APIHost    string
+    APIVersion string
+    APIBuild   string
+    APIBuildNo string
+    CLIVersion string
+    Namespace  string
+    PropsFile  string
 }
 
+const DefaultAuth       string = ""
+const DefaultAPIHost    string = ""
+const DefaultAPIVersion string = "v1"
+const DefaultAPIBuild   string = ""
+const DefaultAPIBuildNo string = ""
+const DefaultNamespace  string = "_"
+const DefaultPropsFile  string = "~/.wskprops"
+
 var propertyCmd = &cobra.Command{
-	Use:   "property",
-	Short: "work with whisk properties",
+    Use:   "property",
+    Short: wski18n.T("work with whisk properties"),
 }
 
+//
+// Set one or more openwhisk property values
+//
 var propertySetCmd = &cobra.Command{
-	Use:   "set",
-	Short: "set property",
-	Run: func(cmd *cobra.Command, args []string) {
-		// get current props
-		props, err := readProps(Properties.PropsFile)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    Use:            "set",
+    Short:          wski18n.T("set property"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var okMsg string = ""
+        var werr *whisk.WskError = nil
 
-		// read in each flag, update if necessary
+        // get current props
+        props, err := readProps(Properties.PropsFile)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "readProps(%s) failed: %s\n", Properties.PropsFile, err)
+            errStr := wski18n.T("Unable to set the property value: {{.err}}", map[string]interface{}{"err": err})
+            werr = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		if auth := flags.global.auth; len(auth) > 0 {
-			props["AUTH"] = auth
-			fmt.Println("ok: whisk auth set")
-		}
+        // read in each flag, update if necessary
 
-		if apiHost := flags.global.apihost; len(apiHost) > 0 {
-			props["APIHOST"] = apiHost
-			fmt.Println("ok: whisk API host set to ", apiHost)
-		}
+        if auth := flags.global.auth; len(auth) > 0 {
+            props["AUTH"] = auth
+            client.Config.AuthToken = auth
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk auth set to {{.auth}}\n",
+                    map[string]interface{}{"ok": color.GreenString("ok:"), "auth": boldString(auth)}))
+        }
 
-		if apiVersion := flags.global.apiversion; len(apiVersion) > 0 {
-			props["APIVERSION"] = apiVersion
-			fmt.Println("ok: whisk API version set to ", apiVersion)
-		}
+        if apiHost := flags.property.apihostSet; len(apiHost) > 0 {
+            baseURL, err := getURLBase(apiHost, DefaultOpenWhiskApiPath)
 
-		if namespace := flags.property.namespaceSet; len(namespace) > 0 {
+            if err != nil {
+                // Not aborting now.  Subsequent commands will result in error
+                whisk.Debug(whisk.DbgError, "getURLBase(%s, %s) error: %s", apiHost, DefaultOpenWhiskApiPath, err)
+                errStr := fmt.Sprintf(
+                    wski18n.T("Unable to set API host value; the API host value '{{.apihost}}' is invalid: {{.err}}",
+                        map[string]interface{}{"apihost": apiHost, "err": err}))
+                werr = whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            } else {
+                props["APIHOST"] = apiHost
+                client.Config.BaseURL = baseURL
+                okMsg += fmt.Sprintf(
+                    wski18n.T("{{.ok}} whisk API host set to {{.host}}\n",
+                        map[string]interface{}{"ok": color.GreenString("ok:"), "host": boldString(apiHost)}))
+            }
+        }
 
-			namespaces, _, err := client.Namespaces.List()
-			if err != nil {
-				fmt.Println(err)
-				return
-			}
+        if apiVersion := flags.property.apiversionSet; len(apiVersion) > 0 {
+            props["APIVERSION"] = apiVersion
+            client.Config.Version = apiVersion
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk API version set to {{.version}}\n",
+                    map[string]interface{}{"ok": color.GreenString("ok:"), "version": boldString(apiVersion)}))
+        }
 
-			var validNamespace bool
-			for _, ns := range namespaces {
-				if ns.Name == namespace {
-					validNamespace = true
-				}
-			}
+        if namespace := flags.property.namespaceSet; len(namespace) > 0 {
+            namespaces, _, err := client.Namespaces.List()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Namespaces.List() failed: %s\n", err)
+                errStr := fmt.Sprintf(
+                    wski18n.T("Authenticated user does not have namespace '{{.name}}'; set command failed: {{.err}}",
+                        map[string]interface{}{"name": namespace, "err": err}))
+                werr = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            } else {
+                whisk.Debug(whisk.DbgInfo, "Validating namespace '%s' is in user namespace list %#v\n", namespace, namespaces)
+                var validNamespace bool
+                for _, ns := range namespaces {
+                    if ns.Name == namespace {
+                        whisk.Debug(whisk.DbgInfo, "Namespace '%s' is valid\n", namespace)
+                        validNamespace = true
+                    }
+                }
+                if !validNamespace {
+                    whisk.Debug(whisk.DbgError, "Namespace '%s' is not in the list of entitled namespaces\n", namespace)
+                    errStr := fmt.Sprintf(
+                        wski18n.T("Namespace '{{.name}}' is not in the list of entitled namespaces",
+                            map[string]interface{}{"name": namespace}))
+                    werr = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                } else {
+                    props["NAMESPACE"] = namespace
+                    okMsg += fmt.Sprintf(
+                        wski18n.T("{{.ok}} whisk namespace set to {{.name}}\n",
+                            map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(namespace)}))
+                }
+            }
+        }
 
-			if !validNamespace {
-				err = fmt.Errorf("Invalid namespace %s", namespace)
-				fmt.Println(err)
-				return
-			}
+        err = writeProps(Properties.PropsFile, props)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "writeProps(%s, %#v) failed: %s\n", Properties.PropsFile, props, err)
+            errStr := fmt.Sprintf(
+                wski18n.T("Unable to set the property value(s): {{.err}}",
+                    map[string]interface{}{"err": err}))
+            werr = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        } else {
+            fmt.Fprintf(color.Output, okMsg)
+        }
 
-			props["NAMESPACE"] = namespace
-			fmt.Println("ok: whisk namespace set to ", namespace)
-		}
+        if (werr != nil) {
+            return werr
+        }
 
-		err = writeProps(Properties.PropsFile, props)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-
-	},
+        return nil
+    },
 }
 
 var propertyUnsetCmd = &cobra.Command{
-	Use:   "unset",
-	Short: "unset property",
-	Run: func(cmd *cobra.Command, args []string) {
-		props, err := readProps(Properties.PropsFile)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+    Use:            "unset",
+    Short:          wski18n.T("unset property"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var okMsg string = ""
+        props, err := readProps(Properties.PropsFile)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "readProps(%s) failed: %s\n", Properties.PropsFile, err)
+            errStr := fmt.Sprintf(
+                wski18n.T("Unable to unset the property value: {{.err}}",
+                    map[string]interface{}{"err": err}))
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		// read in each flag, update if necessary
+        // read in each flag, update if necessary
 
-		if flags.property.auth {
-			delete(props, "AUTH")
-		}
+        if flags.property.auth {
+            delete(props, "AUTH")
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk auth unset",
+                    map[string]interface{}{"ok": color.GreenString("ok:")}))
+            if len(DefaultAuth) > 0 {
+                okMsg += fmt.Sprintf(
+                    wski18n.T("; the default value of {{.default}} will be used.\n",
+                        map[string]interface{}{"default": boldString(DefaultAuth)}))
+            } else {
+                okMsg += fmt.Sprint(
+                    wski18n.T("; there is no default value that can be used.\n"))
+            }
+        }
 
-		if flags.property.namespace {
-			delete(props, "NAMESPACE")
-		}
+        if flags.property.namespace {
+            delete(props, "NAMESPACE")
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk namespace unset",
+                    map[string]interface{}{"ok": color.GreenString("ok:")}))
+            if len(DefaultNamespace) > 0 {
+                okMsg += fmt.Sprintf(
+                    wski18n.T("; the default value of {{.default}} will be used.\n",
+                        map[string]interface{}{"default": boldString(DefaultNamespace)}))
+            } else {
+                okMsg += fmt.Sprint(
+                    wski18n.T("; there is no default value that can be used.\n"))
+            }
+        }
 
-		if flags.property.apihost {
-			delete(props, "APIHOST")
-		}
+        if flags.property.apihost {
+            delete(props, "APIHOST")
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk API host unset",
+                    map[string]interface{}{"ok": color.GreenString("ok:")}))
+            if len(DefaultAPIHost) > 0 {
+                okMsg += fmt.Sprintf(
+                    wski18n.T("; the default value of {{.default}} will be used.\n",
+                        map[string]interface{}{"default": boldString(DefaultAPIHost)}))
+            } else {
+                okMsg += fmt.Sprint(
+                    wski18n.T("; there is no default value that can be used.\n"))
+            }
+        }
 
-		if flags.property.apiversion {
-			delete(props, "APIVERSION")
-		}
+        if flags.property.apiversion {
+            delete(props, "APIVERSION")
+            okMsg += fmt.Sprintf(
+                wski18n.T("{{.ok}} whisk API version unset",
+                    map[string]interface{}{"ok": color.GreenString("ok:")}))
+            if len(DefaultAPIVersion) > 0 {
+                okMsg += fmt.Sprintf(
+                    wski18n.T("; the default value of {{.default}} will be used.\n",
+                        map[string]interface{}{"default": boldString(DefaultAPIVersion)}))
+            } else {
+                okMsg += fmt.Sprint(
+                    wski18n.T("; there is no default value that can be used.\n"))
+            }
+        }
 
-		err = writeProps(Properties.PropsFile, props)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-	},
+        err = writeProps(Properties.PropsFile, props)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "writeProps(%s, %#v) failed: %s\n", Properties.PropsFile, props, err)
+            errStr := fmt.Sprintf(
+                wski18n.T("Unable to unset the property value: {{.err}}",
+                    map[string]interface{}{"err": err}))
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output, okMsg)
+        if err = loadProperties(); err != nil {
+            whisk.Debug(whisk.DbgError, "loadProperties() failed: %s\n", err)
+        }
+        return nil
+    },
 }
 
 var propertyGetCmd = &cobra.Command{
-	Use:   "get",
-	Short: "get property",
-	Run: func(cmd *cobra.Command, args []string) {
+    Use:            "get",
+    Short:          wski18n.T("get property"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
 
-		if flags.property.all || flags.property.auth {
-			fmt.Println("whisk auth\t\t", Properties.Auth)
-		}
+        // If no property is explicitly specified, default to all properties
+        if !(flags.property.all || flags.property.auth ||
+             flags.property.apiversion || flags.property.cliversion ||
+             flags.property.namespace || flags.property.apibuild ||
+             flags.property.apihost || flags.property.apibuildno) {
+            flags.property.all = true
+        }
 
-		if flags.property.all || flags.property.apihost {
-			fmt.Println("whisk API host\t\t", Properties.APIHost)
-		}
+        if flags.property.all || flags.property.auth {
+            fmt.Fprintf(color.Output, "%s\t\t%s\n", wski18n.T("whisk auth"), boldString(Properties.Auth))
+        }
 
-		if flags.property.all || flags.property.apiversion {
-			fmt.Println("whisk API version\t", Properties.APIVersion)
-		}
+        if flags.property.all || flags.property.apihost {
+            fmt.Fprintf(color.Output, "%s\t\t%s\n", wski18n.T("whisk API host"), boldString(Properties.APIHost))
+        }
 
-		if flags.property.all || flags.property.cliversion {
-			fmt.Println("whisk CLI version\t", Properties.CLIVersion)
-		}
+        if flags.property.all || flags.property.apiversion {
+            fmt.Fprintf(color.Output, "%s\t%s\n", wski18n.T("whisk API version"), boldString(Properties.APIVersion))
+        }
 
-		if flags.property.all || flags.property.namespace {
-			fmt.Println("whisk namespace\t\t", Properties.Namespace)
-		}
+        if flags.property.all || flags.property.namespace {
+            fmt.Fprintf(color.Output, "%s\t\t%s\n", wski18n.T("whisk namespace"), boldString(Properties.Namespace))
+        }
 
-		if flags.property.all || flags.property.apibuild {
-			info, _, err := client.Info.Get()
-			if err != nil {
-				fmt.Println(err)
-			} else {
-				fmt.Println("whisk API build\t\t", info.Build)
-			}
-		}
+        if flags.property.all || flags.property.cliversion {
+            fmt.Fprintf(color.Output, "%s\t%s\n", wski18n.T("whisk CLI version"), boldString(Properties.CLIVersion))
+        }
 
-	},
+        if flags.property.all || flags.property.apibuild || flags.property.apibuildno {
+            info, _, err := client.Info.Get()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Info.Get() failed: %s\n", err)
+                info = &whisk.Info{}
+                info.Build = wski18n.T("Unknown")
+                info.BuildNo = wski18n.T("Unknown")
+            }
+            if flags.property.all || flags.property.apibuild {
+                fmt.Fprintf(color.Output, "%s\t\t%s\n", wski18n.T("whisk API build"), boldString(info.Build))
+            }
+            if flags.property.all || flags.property.apibuildno {
+                fmt.Fprintf(color.Output, "%s\t%s\n", wski18n.T("whisk API build number"), boldString(info.BuildNo))
+            }
+            if err != nil {
+                errStr := fmt.Sprintf(
+                    wski18n.T("Unable to obtain API build information: {{.err}}",
+                        map[string]interface{}{"err": err}))
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
+
+        return nil
+    },
 }
 
 func init() {
-	propertyCmd.AddCommand(
-		propertySetCmd,
-		propertyUnsetCmd,
-		propertyGetCmd,
-	)
+    propertyCmd.AddCommand(
+        propertySetCmd,
+        propertyUnsetCmd,
+        propertyGetCmd,
+    )
 
-	// need to set property flags as booleans instead of strings... perhaps with boolApihost...
-	propertyGetCmd.Flags().BoolVarP(&flags.property.auth, "auth", "u", false, "authorization key")
-	propertyGetCmd.Flags().BoolVar(&flags.property.apihost, "apihost", false, "whisk API host")
-	propertyGetCmd.Flags().BoolVar(&flags.property.apiversion, "apiversion", false, "whisk API version")
-	propertyGetCmd.Flags().BoolVar(&flags.property.apibuild, "apibuild", false, "whisk API build version")
-	propertyGetCmd.Flags().BoolVar(&flags.property.cliversion, "cliversion", false, "whisk CLI version")
-	propertyGetCmd.Flags().BoolVar(&flags.property.namespace, "namespace", false, "authorization key")
-	propertyGetCmd.Flags().BoolVar(&flags.property.all, "all", false, "all properties")
+    // need to set property flags as booleans instead of strings... perhaps with boolApihost...
+    propertyGetCmd.Flags().BoolVar(&flags.property.auth, "auth", false, wski18n.T("authorization key"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.apihost, "apihost", false, wski18n.T("whisk API host"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.apiversion, "apiversion", false, wski18n.T("whisk API version"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.apibuild, "apibuild", false, wski18n.T("whisk API build version"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.apibuildno, "apibuildno", false, wski18n.T("whisk API build number"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.cliversion, "cliversion", false, wski18n.T("whisk CLI version"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.namespace, "namespace", false, wski18n.T("whisk namespace"))
+    propertyGetCmd.Flags().BoolVar(&flags.property.all, "all", false, wski18n.T("all properties"))
 
-	propertySetCmd.Flags().StringVarP(&flags.global.auth, "auth", "u", "", "authorization key")
-	propertySetCmd.Flags().StringVar(&flags.property.apihostSet, "apihost", "", "whisk API host")
-	propertySetCmd.Flags().StringVar(&flags.property.apiversionSet, "apiversion", "", "whisk API version")
-	propertySetCmd.Flags().StringVar(&flags.property.namespaceSet, "namespace", "", "whisk namespace")
+    propertySetCmd.Flags().StringVarP(&flags.global.auth, "auth", "u", "", wski18n.T("authorization `KEY`"))
+    propertySetCmd.Flags().StringVar(&flags.property.apihostSet, "apihost", "", wski18n.T("whisk API `HOST`"))
+    propertySetCmd.Flags().StringVar(&flags.property.apiversionSet, "apiversion", "", wski18n.T("whisk API `VERSION`"))
+    propertySetCmd.Flags().StringVar(&flags.property.namespaceSet, "namespace", "", wski18n.T("whisk `NAMESPACE`"))
 
-	propertyUnsetCmd.Flags().BoolVarP(&flags.property.auth, "auth", "u", false, "authorization key")
-	propertyUnsetCmd.Flags().BoolVar(&flags.property.apihost, "apihost", false, "whisk API host")
-	propertyUnsetCmd.Flags().BoolVar(&flags.property.apiversion, "apiversion", false, "whisk API version")
-	propertyUnsetCmd.Flags().BoolVar(&flags.property.namespace, "namespace", false, "whisk namespace")
+    propertyUnsetCmd.Flags().BoolVar(&flags.property.auth, "auth", false, wski18n.T("authorization key"))
+    propertyUnsetCmd.Flags().BoolVar(&flags.property.apihost, "apihost", false, wski18n.T("whisk API host"))
+    propertyUnsetCmd.Flags().BoolVar(&flags.property.apiversion, "apiversion", false, wski18n.T("whisk API version"))
+    propertyUnsetCmd.Flags().BoolVar(&flags.property.namespace, "namespace", false, wski18n.T("whisk namespace"))
 
 }
 
 func setDefaultProperties() {
-	Properties.Auth = ""
-	Properties.Namespace = "_"
-	Properties.APIHost = "https://openwhisk.ng.bluemix.net/api/"
-	Properties.APIBuild = ""
-	Properties.APIVersion = "v1"
-	Properties.CLIVersion = ""
-	Properties.PropsFile = "~/.wskprops"
+    Properties.Auth = DefaultAuth
+    Properties.Namespace = DefaultNamespace
+    Properties.APIHost = DefaultAPIHost
+    Properties.APIBuild = DefaultAPIBuild
+    Properties.APIBuildNo = DefaultAPIBuildNo
+    Properties.APIVersion = DefaultAPIVersion
+    Properties.PropsFile = DefaultPropsFile
+    // Properties.CLIVersion value is set from main's init()
+}
+
+func getPropertiesFilePath() (propsFilePath string, werr error) {
+    var envExists bool
+
+    // Environment variable overrides the default properties file path
+    if propsFilePath, envExists = os.LookupEnv("WSK_CONFIG_FILE"); envExists == true || propsFilePath != "" {
+        whisk.Debug(whisk.DbgInfo, "Using properties file '%s' from WSK_CONFIG_FILE environment variable\n", propsFilePath)
+        return propsFilePath, nil
+    } else {
+        var err error
+
+        propsFilePath, err = homedir.Expand(Properties.PropsFile)
+
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "homedir.Expand(%s) failed: %s\n", Properties.PropsFile, err)
+            errStr := fmt.Sprintf(
+                wski18n.T("Unable to locate properties file '{{.filename}}': {{.err}}",
+                    map[string]interface{}{"filename": Properties.PropsFile, "err": err}))
+            werr = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return propsFilePath, werr
+        }
+
+        whisk.Debug(whisk.DbgInfo, "Using properties file home dir '%s'\n", propsFilePath)
+    }
+
+    return propsFilePath, nil
 }
 
 func loadProperties() error {
-	var err error
+    var err error
 
-	setDefaultProperties()
+    setDefaultProperties()
 
-	Properties.PropsFile, err = homedir.Expand(Properties.PropsFile)
-	if err != nil {
-		return err
-	}
+    Properties.PropsFile, err = getPropertiesFilePath()
+    if err != nil {
+        return nil
+        //whisk.Debug(whisk.DbgError, "getPropertiesFilePath() failed: %s\n", err)
+        //errStr := fmt.Sprintf("Unable to load the properties file: %s", err)
+        //werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        //return werr
+    }
 
-	props, err := readProps(Properties.PropsFile)
-	if err != nil {
-		return err
-	}
+    props, err := readProps(Properties.PropsFile)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "readProps(%s) failed: %s\n", Properties.PropsFile, err)
+        errStr := wski18n.T("Unable to read the properties file '{{.filename}}': {{.err}}",
+                map[string]interface{}{"filename": Properties.PropsFile, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
 
-	if authToken, hasProp := props["AUTH"]; hasProp {
-		Properties.Auth = authToken
-	}
+    if authToken, hasProp := props["AUTH"]; hasProp {
+        Properties.Auth = authToken
+    }
 
-	if authToken := os.Getenv("WHISK_AUTH"); len(authToken) > 0 {
-		Properties.Auth = authToken
-	}
+    if authToken := os.Getenv("WHISK_AUTH"); len(authToken) > 0 {
+        Properties.Auth = authToken
+    }
 
-	if apiVersion, hasProp := props["APIVERSION"]; hasProp {
-		Properties.APIVersion = apiVersion
-	}
+    if apiVersion, hasProp := props["APIVERSION"]; hasProp {
+        Properties.APIVersion = apiVersion
+    }
 
-	if apiVersion := os.Getenv("WHISK_APIVERSION"); len(apiVersion) > 0 {
-		Properties.APIVersion = apiVersion
-	}
+    if apiVersion := os.Getenv("WHISK_APIVERSION"); len(apiVersion) > 0 {
+        Properties.APIVersion = apiVersion
+    }
 
-	if apiHost, hasProp := props["APIHOST"]; hasProp {
-		Properties.APIHost = apiHost
-	}
+    if apiHost, hasProp := props["APIHOST"]; hasProp {
+        Properties.APIHost = apiHost
+    }
 
-	if apiHost := os.Getenv("WHISK_APIHOST"); len(apiHost) > 0 {
-		Properties.APIHost = apiHost
-	}
+    if apiHost := os.Getenv("WHISK_APIHOST"); len(apiHost) > 0 {
+        Properties.APIHost = apiHost
+    }
 
-	if namespace, hasProp := props["NAMESPACE"]; hasProp {
-		Properties.Namespace = namespace
-	}
+    if namespace, hasProp := props["NAMESPACE"]; hasProp && len(namespace) > 0 {
+        Properties.Namespace = namespace
+    }
 
-	if namespace := os.Getenv("WHISK_NAMESPACE"); len(namespace) > 0 {
-		Properties.Namespace = namespace
-	}
+    if namespace := os.Getenv("WHISK_NAMESPACE"); len(namespace) > 0 {
+        Properties.Namespace = namespace
+    }
 
-	return nil
+    return nil
 }
 
-func parseConfigFlags(cmd *cobra.Command, args []string) {
+func parseConfigFlags(cmd *cobra.Command, args []string) error {
 
-	if auth := flags.global.auth; len(auth) > 0 {
-		Properties.Auth = auth
-		client.Config.AuthToken = auth
-	}
+    if auth := flags.global.auth; len(auth) > 0 {
+        Properties.Auth = auth
+        if client != nil {
+            client.Config.AuthToken = auth
+        }
+    }
 
-	if namespace := flags.property.namespaceSet; len(namespace) > 0 {
-		Properties.Namespace = namespace
-		client.Config.Namespace = namespace
-	}
+    if namespace := flags.property.namespaceSet; len(namespace) > 0 {
+        Properties.Namespace = namespace
+        if client != nil {
+            client.Config.Namespace = namespace
+        }
+    }
 
-	if apiVersion := flags.global.apiversion; len(apiVersion) > 0 {
-		Properties.APIVersion = apiVersion
-		client.Config.Version = apiVersion
-	}
+    if apiVersion := flags.global.apiversion; len(apiVersion) > 0 {
+        Properties.APIVersion = apiVersion
+        if client != nil {
+            client.Config.Version = apiVersion
+        }
+    }
 
-	if apiHost := flags.global.apihost; len(apiHost) > 0 {
-		fmt.Println(apiHost)
-		Properties.APIHost = apiHost
-		u, err := url.ParseRequestURI(apiHost)
-		if err == nil {
-			client.Config.BaseURL = u
-		} else {
-			fmt.Println(err)
-			os.Exit(-1)
-		}
-	}
+    if apiHost := flags.global.apihost; len(apiHost) > 0 {
+        Properties.APIHost = apiHost
 
-	if flags.global.verbose {
-		client.Config.Verbose = flags.global.verbose
-	}
-}
+        if client != nil {
+            client.Config.Host = apiHost
+            baseURL, err := getURLBase(apiHost, DefaultOpenWhiskApiPath)
 
-func readProps(path string) (map[string]string, error) {
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "getURLBase(%s, %s) failed: %s\n", apiHost, DefaultOpenWhiskApiPath, err)
+                errStr := wski18n.T("Invalid host address '{{.host}}': {{.err}}",
+                        map[string]interface{}{"host": Properties.APIHost, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            client.Config.BaseURL = baseURL
+        }
+    }
 
-	props := map[string]string{}
+    if flags.global.debug {
+        whisk.SetDebug(true)
+    }
+    if flags.global.verbose {
+        whisk.SetVerbose(true)
+    }
 
-	file, err := os.Open(path)
-	if err != nil {
-		// If file does not exist, just return props
-		return props, nil
-	}
-	defer file.Close()
-
-	lines := []string{}
-	scanner := bufio.NewScanner(file)
-	for scanner.Scan() {
-		lines = append(lines, scanner.Text())
-	}
-
-	props = map[string]string{}
-	for _, line := range lines {
-		kv := strings.Split(line, "=")
-		if len(kv) != 2 {
-			// Invalid format; skip
-			continue
-		}
-		props[kv[0]] = kv[1]
-	}
-
-	return props, nil
-
-}
-
-func writeProps(path string, props map[string]string) error {
-
-	file, err := os.Create(path)
-	if err != nil {
-		return err
-	}
-	defer file.Close()
-
-	writer := bufio.NewWriter(file)
-	defer writer.Flush()
-	for key, value := range props {
-		line := fmt.Sprintf("%s=%s", strings.ToUpper(key), value)
-		_, err = fmt.Fprintln(writer, line)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
+    return nil
 }
diff --git a/commands/rule.go b/commands/rule.go
index 3fc1cd6..b537aff 100644
--- a/commands/rule.go
+++ b/commands/rule.go
@@ -1,269 +1,455 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"errors"
-	"fmt"
+    "errors"
+    "fmt"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 
-	"github.com/fatih/color"
-	"github.com/spf13/cobra"
+    "github.com/fatih/color"
+    "github.com/spf13/cobra"
 )
 
 // ruleCmd represents the rule command
 var ruleCmd = &cobra.Command{
-	Use:   "rule",
-	Short: "work with rules",
+    Use:   "rule",
+    Short: wski18n.T("work with rules"),
 }
 
 var ruleEnableCmd = &cobra.Command{
-	Use:   "enable <name string>",
-	Short: "enable rule",
+    Use:   "enable RULE_NAME",
+    Short: wski18n.T("enable rule"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 1, "Rule enable", wski18n.T("A rule name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		ruleName := args[0]
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
 
-		_, _, err = client.Rules.SetState(ruleName, "enable")
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Printf("%s enabled rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-	},
+        _, _, err = client.Rules.SetState(ruleName, "active")
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.SetState(%s, active) failed: %s\n", ruleName, err)
+            errStr := wski18n.T("Unable to enable rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} enabled rule {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+        return nil
+    },
 }
 
 var ruleDisableCmd = &cobra.Command{
-	Use:   "disable <name string>",
-	Short: "disable rule",
+    Use:   "disable RULE_NAME",
+    Short: wski18n.T("disable rule"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 1, "Rule disable", wski18n.T("A rule name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		ruleName := args[0]
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
 
-		_, _, err = client.Rules.SetState(ruleName, "disable")
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Printf("%s disabled rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-	},
+        _, _, err = client.Rules.SetState(ruleName, "inactive")
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.SetState(%s, inactive) failed: %s\n", ruleName, err)
+            errStr := wski18n.T("Unable to disable rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} disabled rule {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+        return nil
+    },
 }
 
 var ruleStatusCmd = &cobra.Command{
-	Use:   "status <name string>",
-	Short: "get rule status",
+    Use:   "status RULE_NAME",
+    Short: wski18n.T("get rule status"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		// TODO: how is this different than "rule get" ??
-		fmt.Println("rule status called")
-	},
+        if whiskErr := checkArgs(args, 1, 1, "Rule status", wski18n.T("A rule name is required.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
+
+        rule, _, err := client.Rules.Get(ruleName)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.Get(%s) failed: %s\n", ruleName, err)
+            errStr := wski18n.T("Unable to get status of rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} rule {{.name}} is {{.status}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName), "status": boldString(rule.Status)}))
+        return nil
+    },
 }
 
 var ruleCreateCmd = &cobra.Command{
-	Use:   "create <name string> <trigger string> <action string>",
-	Short: "create new rule",
+    Use:   "create RULE_NAME TRIGGER_NAME ACTION_NAME",
+    Short: wski18n.T("create new rule"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 3 {
-			err = errors.New("Invalid argument list")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 3, 3, "Rule create",
+                wski18n.T("A rule, trigger and action name are required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		ruleName := args[0]
-		triggerName := args[1]
-		actionName := args[2]
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		rule := &whisk.Rule{
-			Name:    ruleName,
-			Trigger: triggerName,
-			Action:  actionName,
-			Publish: flags.common.shared,
-		}
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
+        triggerName := getQualifiedName(args[1], Properties.Namespace)
+        actionName := getQualifiedName(args[2], Properties.Namespace)
 
-		rule, _, err = client.Rules.Insert(rule, false)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        rule := &whisk.Rule{
+            Name:    ruleName,
+            Trigger: triggerName,
+            Action:  actionName,
+        }
 
-		if flags.rule.enable {
-			rule, _, err = client.Rules.SetState(ruleName, "enabled")
-			if err != nil {
-				fmt.Println(err)
-				return
-			}
-		}
+        whisk.Debug(whisk.DbgInfo, "Inserting rule:\n%+v\n", rule)
+        var retRule *whisk.Rule
+        retRule, _, err = client.Rules.Insert(rule, false)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.Insert(%#v) failed: %s\n", rule, err)
+            errStr := wski18n.T("Unable to create rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+        whisk.Debug(whisk.DbgInfo, "Inserted rule:\n%+v\n", retRule)
 
-		fmt.Printf("%s created rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-	},
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} created rule {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+        return nil
+    },
 }
 
 var ruleUpdateCmd = &cobra.Command{
-	Use:   "update <name string> <trigger string> <action string>",
-	Short: "update existing rule",
+    Use:   "update RULE_NAME TRIGGER_NAME ACTION_NAME",
+    Short: wski18n.T("update an existing rule, or create a rule if it does not exist"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 3 {
-			err = errors.New("Invalid argument list")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 3, 3, "Rule update",
+                wski18n.T("A rule, trigger and action name are required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		ruleName := args[0]
-		triggerName := args[1]
-		actionName := args[2]
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		rule := &whisk.Rule{
-			Name:    ruleName,
-			Trigger: triggerName,
-			Action:  actionName,
-			Publish: flags.common.shared,
-		}
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
+        triggerName := getQualifiedName(args[1], Properties.Namespace)
+        actionName := getQualifiedName(args[2], Properties.Namespace)
 
-		rule, _, err = client.Rules.Insert(rule, true)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Printf("%s updated rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-	},
+        rule := &whisk.Rule{
+            Name:    ruleName,
+            Trigger: triggerName,
+            Action:  actionName,
+        }
+
+        _, _, err = client.Rules.Insert(rule, true)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.Insert(%#v) failed: %s\n", rule, err)
+            errStr := wski18n.T("Unable to update rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": rule.Name, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} updated rule {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+        return nil
+    },
 }
 
 var ruleGetCmd = &cobra.Command{
-	Use:   "get <name string>",
-	Short: "get rule",
+    Use:   "get RULE_NAME",
+    Short: wski18n.T("get rule"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var field string
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 2, "Rule get", wski18n.T("A rule name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		ruleName := args[0]
+        if len(args) > 1 {
+            field = args[1]
 
-		rule, _, err := client.Rules.Get(ruleName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Printf("%s got rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-		printJSON(rule)
-	},
+            if !fieldExists(&whisk.Rule{}, field){
+                errMsg := wski18n.T("Invalid field filter '{{.arg}}'.", map[string]interface{}{"arg": field})
+                whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
+
+        rule, _, err := client.Rules.Get(ruleName)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.Get(%s) failed: %s\n", ruleName, err)
+            errStr := wski18n.T("Unable to get rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
+
+        if (flags.rule.summary) {
+            printRuleSummary(rule)
+        } else {
+            if len(field) > 0 {
+                fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got rule {{.name}}, displaying field {{.field}}\n",
+                    map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName),
+                        "field": field}))
+                printField(rule, field)
+            } else {
+                fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got rule {{.name}}\n",
+                        map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+                printJSON(rule)
+            }
+        }
+
+        return nil
+    },
 }
 
 var ruleDeleteCmd = &cobra.Command{
-	Use:   "delete <name string>",
-	Short: "delete rule",
+    Use:   "delete RULE_NAME",
+    Short: wski18n.T("delete rule"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 1, "Rule delete", wski18n.T("A rule name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		ruleName := args[0]
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		if flags.rule.disable {
-			_, _, err := client.Rules.SetState(ruleName, "disabled")
-			if err != nil {
-				fmt.Println(err)
-				return
-			}
-		}
+        client.Namespace = qName.namespace
+        ruleName := qName.entityName
 
-		_, err = client.Rules.Delete(ruleName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Printf("%s deleted rule %s\n", color.GreenString("ok:"), boldString(ruleName))
-	},
+        if flags.rule.disable {
+            _, _, err := client.Rules.SetState(ruleName, "inactive")
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Rules.SetState(%s, inactive) failed: %s\n", ruleName, err)
+                errStr := wski18n.T("Unable to disable rule '{{.name}}': {{.err}}",
+                        map[string]interface{}{"name": ruleName, "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
+
+        _, err = client.Rules.Delete(ruleName)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.Delete(%s) error: %s\n", ruleName, err)
+            errStr := wski18n.T("Unable to delete rule '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": ruleName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} deleted rule {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(ruleName)}))
+        return nil
+    },
 }
 
 var ruleListCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list all rules",
+    Use:   "list [NAMESPACE]",
+    Short: wski18n.T("list all rules"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        qName := QualifiedName{}
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		qName := qualifiedName{}
-		if len(args) == 1 {
-			qName, err = parseQualifiedName(args[0])
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
-			ns := qName.namespace
-			if len(ns) == 0 {
-				err = errors.New("No valid namespace detected.  Make sure that namespace argument is preceded by a \"/\"")
-				fmt.Printf("error: %s\n", err)
-				return
-			}
+        if len(args) == 1 {
+            qName, err = parseQualifiedName(args[0])
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+                errStr := wski18n.T("Namespace '{{.name}}' is invalid: {{.err}}\n",
+                        map[string]interface{}{"name": args[0], "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            ns := qName.namespace
+            if len(ns) == 0 {
+                whisk.Debug(whisk.DbgError, "Namespace is missing from '%s'\n", args[0])
+                errStr := wski18n.T("No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\"")
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
+            client.Namespace = ns
+        } else if whiskErr := checkArgs(args, 0, 1, "Rule list",
+                wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-			client.Namespace = ns
+        ruleListOptions := &whisk.RuleListOptions{
+            Skip:  flags.common.skip,
+            Limit: flags.common.limit,
+        }
 
-			if pkg := qName.packageName; len(pkg) > 0 {
-				// todo :: scope call to package
-			}
-		}
-
-		ruleListOptions := &whisk.RuleListOptions{
-			Skip:  flags.common.skip,
-			Limit: flags.common.limit,
-		}
-
-		rules, _, err := client.Rules.List(ruleListOptions)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		printList(rules)
-	},
+        rules, _, err := client.Rules.List(ruleListOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Rules.List(%#v) error: %s\n", ruleListOptions, err)
+            errStr := wski18n.T("Unable to obtain the list of rules for namespace '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": getClientNamespace(), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+        printList(rules)
+        return nil
+    },
 }
 
 func init() {
+    ruleDeleteCmd.Flags().BoolVar(&flags.rule.disable, "disable", false, wski18n.T("automatically disable rule before deleting it"))
 
-	ruleCreateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
-	ruleCreateCmd.Flags().BoolVar(&flags.rule.enable, "enable", false, "autmatically enable rule after creating it")
+    ruleGetCmd.Flags().BoolVarP(&flags.rule.summary, "summary", "s", false, wski18n.T("summarize rule details"))
 
-	ruleUpdateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
+    ruleListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of rules from the result"))
+    ruleListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of rules from the collection"))
 
-	ruleDeleteCmd.Flags().BoolVar(&flags.rule.disable, "disable", false, "autmatically disable rule before deleting it")
-
-	ruleListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, "skip this many entities from the head of the collection")
-	ruleListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, "only return this many entities from the collection")
-
-	ruleCmd.AddCommand(
-		ruleEnableCmd,
-		ruleDisableCmd,
-		ruleStatusCmd,
-		ruleCreateCmd,
-		ruleUpdateCmd,
-		ruleGetCmd,
-		ruleDeleteCmd,
-		ruleListCmd,
-	)
+    ruleCmd.AddCommand(
+        ruleCreateCmd,
+        ruleEnableCmd,
+        ruleDisableCmd,
+        ruleStatusCmd,
+        ruleUpdateCmd,
+        ruleGetCmd,
+        ruleDeleteCmd,
+        ruleListCmd,
+    )
 
 }
diff --git a/commands/sdk.go b/commands/sdk.go
index 85cee68..aed876a 100644
--- a/commands/sdk.go
+++ b/commands/sdk.go
@@ -1,112 +1,245 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"errors"
-	"fmt"
-	"os"
-	"os/exec"
+    "errors"
+    "fmt"
+    "io"
+    "os"
+    "strings"
 
-	"github.com/spf13/cobra"
+    "github.com/spf13/cobra"
+
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 )
 
 // sdkCmd represents the sdk command
 var sdkCmd = &cobra.Command{
-	Use:   "sdk",
-	Short: "work with the sdk",
+    Use:   "sdk",
+    Short: wski18n.T("work with the sdk"),
 }
 
-var sdkInstallCmd = &cobra.Command{
-	Use:   "install <component string:{docker,swift,iOS}>",
-	Short: "install artifacts",
+type sdkInfo struct {
+    UrlPath   string
+    FileName  string
+    isGzTar   bool
+    IsGzip    bool
+    IsZip     bool
+    IsTar     bool
+    Unpack    bool
+    UnpackDir string
+}
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err := errors.New("Invalid component argument")
-			fmt.Println(err)
-			return
-		}
-		component := args[0]
-		switch component {
-		case "docker":
-			err = dockerInstall()
-		case "swift":
-			err = swiftInstall()
-		case "iOS":
-			err = iOSInstall()
-		default:
-			err = errors.New("Invalid component argument")
-		}
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-	},
+var sdkMap map[string]*sdkInfo
+const SDK_DOCKER_COMPONENT_NAME string = "docker"
+const SDK_IOS_COMPONENT_NAME string = "ios"
+const BASH_AUTOCOMPLETE_FILENAME string = "wsk_cli_bash_completion.sh"
+
+var sdkInstallCmd = &cobra.Command{
+    Use:   "install COMPONENT",
+    Short: wski18n.T("install SDK artifacts"),
+    Long: wski18n.T("install SDK artifacts, where valid COMPONENT values are docker, ios, and bashauto"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        if len(args) != 1 {
+            whisk.Debug(whisk.DbgError, "Invalid number of arguments: %d\n", len(args))
+            errStr := wski18n.T("The SDK component argument is missing. One component (docker, ios, or bashauto) must be specified")
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
+        component := strings.ToLower(args[0])
+        switch component {
+        case "docker":
+            err = dockerInstall()
+        case "ios":
+            err = iOSInstall()
+        case "bashauto":
+            err = WskCmd.GenBashCompletionFile(BASH_AUTOCOMPLETE_FILENAME)
+            if (err != nil) {
+                whisk.Debug(whisk.DbgError, "GenBashCompletionFile('%s`) error: \n", BASH_AUTOCOMPLETE_FILENAME, err)
+                errStr := wski18n.T("Unable to generate '{{.name}}': {{.err}}",
+                        map[string]interface{}{"name": BASH_AUTOCOMPLETE_FILENAME, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            fmt.Printf(
+                wski18n.T("bash_completion_msg",
+                    map[string]interface{}{"name": BASH_AUTOCOMPLETE_FILENAME}))
+        default:
+            whisk.Debug(whisk.DbgError, "Invalid component argument '%s'\n", component)
+            errStr := wski18n.T("The SDK component argument '{{.component}}' is invalid. Valid components are docker, ios and bashauto",
+                    map[string]interface{}{"component": component})
+            err = whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        }
+
+        if err != nil {
+            return err
+        }
+        return nil
+    },
 }
 
 func dockerInstall() error {
-	var err error
-	tarFile := "blackbox-0.1.0.tar.gz"
-	blackboxDir := "dockerSkeleton"
-	if _, err = os.Stat(tarFile); err == nil {
-		err = fmt.Errorf("The path %s already exists.  Please deleted it and retry.", tarFile)
-		return err
-	}
+    var err error
 
-	if _, err = os.Stat(blackboxDir); err == nil {
-		err = fmt.Errorf("The path %s already exists.  Please deleted it and retry.", blackboxDir)
-		return err
-	}
+    targetFile := sdkMap[SDK_DOCKER_COMPONENT_NAME].FileName
+    if _, err = os.Stat(targetFile); err == nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' exists\n", targetFile)
+        errStr := wski18n.T("The file {{.name}} already exists.  Delete it and retry.",
+            map[string]interface{}{"name": targetFile})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
 
-	downloadCmd := exec.Command("wget", "--quiet", "--no-check-certificate", "https://whisk.sl.cloud9.ibm.com/"+tarFile)
+    if err = sdkInstall(SDK_DOCKER_COMPONENT_NAME); err != nil {
+        whisk.Debug(whisk.DbgError, "sdkInstall(%s) failed: %s\n", SDK_DOCKER_COMPONENT_NAME, err)
+        errStr := wski18n.T("The {{.component}} SDK installation failed: {{.err}}",
+                map[string]interface{}{"component": SDK_DOCKER_COMPONENT_NAME, "err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
 
-	if err = downloadCmd.Run(); err != nil {
-		err = errors.New("Download of docker skeleton failed")
-		return err
-	}
-
-	installCmd := exec.Command("tar", "pxf", tarFile)
-
-	if err = installCmd.Run(); err != nil {
-		err = errors.New("Could not install docker skeleton")
-		return err
-	}
-
-	rmCmd := exec.Command("rm", tarFile)
-	if err = rmCmd.Run(); err != nil {
-		// Don't really care...
-	}
-
-	fmt.Println("The docker skeleton is now installed at the current directory.")
-
-	return nil
-}
-
-func swiftInstall() error {
-	fmt.Println("swift SDK coming soon")
-	return nil
+    fmt.Println(wski18n.T("The docker skeleton is now installed at the current directory."))
+    return nil
 }
 
 func iOSInstall() error {
-	var err error
-	zipFile := "WhiskIOSStarterApp.zip"
-	if _, err = os.Stat(zipFile); err == nil {
-		err = fmt.Errorf("The path %s already exists.  Please delete it and try again", zipFile)
-		return err
-	}
+    var err error
 
-	url := fmt.Sprintf("https://%s/%s", Properties.APIHost, zipFile)
-	downloadCmd := exec.Command("wget", "--quiet", "--no-check-certificate", url)
-	if err = downloadCmd.Run(); err != nil {
-		err = errors.New("Download of iOS Whisk starter app failed.")
-		return err
-	}
+    if err = sdkInstall(SDK_IOS_COMPONENT_NAME); err != nil {
+        whisk.Debug(whisk.DbgError, "sdkInstall(%s) failed: %s\n", SDK_IOS_COMPONENT_NAME, err)
+        errStr := wski18n.T("The {{.component}} SDK installation failed: {{.err}}",
+                map[string]interface{}{"component": SDK_IOS_COMPONENT_NAME, "err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
 
-	fmt.Printf("Downloaded iOS whisk starter app. Unzip %s and open the project in Xcode", zipFile)
+    fmt.Printf(
+        wski18n.T("Downloaded OpenWhisk iOS starter app. Unzip {{.name}} and open the project in Xcode.\n",
+            map[string]interface{}{"name": sdkMap[SDK_IOS_COMPONENT_NAME].FileName}))
+    return nil
+}
 
-	return nil
+func sdkInstall(componentName string) error {
+    targetFile := sdkMap[componentName].FileName
+    if _, err := os.Stat(targetFile); err == nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' exists\n", targetFile)
+        errStr := wski18n.T("The file {{.name}} already exists.  Delete it and retry.",
+                map[string]interface{}{"name": targetFile})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    resp, err := client.Sdks.Install(sdkMap[componentName].UrlPath)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "client.Sdks.Install(%s) failed: %s\n", sdkMap[componentName].UrlPath, err)
+        errStr := wski18n.T("Unable to retrieve '{{.urlpath}}' SDK: {{.err}}",
+                map[string]interface{}{"urlpath": sdkMap[componentName].UrlPath, "err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    if resp.Body == nil {
+        whisk.Debug(whisk.DbgError, "SDK Install HTTP response has no body\n")
+        errStr := wski18n.T("Server failed to send the '{{.component}}' SDK: {{.err}}",
+                map[string]interface{}{"name": componentName, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_NETWORK, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    // Create the SDK file
+    sdkfile, err := os.Create(targetFile)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Create(%s) failure: %s\n", targetFile, err)
+        errStr := wski18n.T("Error creating SDK file {{.name}}: {{.err}}",
+                map[string]interface{}{"name": targetFile, "err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    // Read the HTTP response body and write it to the SDK file
+    whisk.Debug(whisk.DbgInfo, "Reading SDK file from HTTP response body\n")
+    _, err = io.Copy(sdkfile, resp.Body)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "io.Copy() of resp.Body into sdkfile failure: %s\n", err)
+        errStr := wski18n.T("Error copying server response into file: {{.err}}",
+                map[string]interface{}{"err": err})
+        werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        sdkfile.Close()
+        return werr
+
+    }
+    sdkfile.Close()     // Don't use 'defer' since this file might need to be deleted after unpack
+
+    // At this point, the entire file is downloaded from the server
+    // Check if there is any special post-download processing (i.e. unpack)
+    if sdkMap[componentName].Unpack {
+        // Make sure the target directory does not already exist
+        defer os.Remove(targetFile)
+        targetdir := sdkMap[componentName].UnpackDir
+        if _, err = os.Stat(targetdir); err == nil {
+            whisk.Debug(whisk.DbgError, "os.Stat reports that directory '%s' exists\n", targetdir)
+            errStr := wski18n.T("The directory {{.name}} already exists.  Delete it and retry.",
+                    map[string]interface{}{"name": targetdir})
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        // If the packed SDK is a .tgz file, unpack it in two steps
+        // 1. UnGzip into temp .tar file
+        // 2. Untar the contents into the current folder
+        if sdkMap[componentName].isGzTar {
+            whisk.Debug(whisk.DbgInfo, "unGzipping downloaded file\n")
+            err := unpackGzip(targetFile, "temp.tar")
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "unpackGzip(%s,temp.tar) failure: %s\n", targetFile, err)
+                errStr := wski18n.T("Error unGzipping file {{.name}}: {{.err}}",
+                    map[string]interface{}{"name": targetFile, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            defer os.Remove("temp.tar")
+
+            whisk.Debug(whisk.DbgInfo, "unTarring unGzipped file\n")
+            err = unpackTar("temp.tar")
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "unpackTar(temp.tar) failure: %s\n", err)
+                errStr := wski18n.T("Error untarring file {{.name}}: {{.err}}",
+                        map[string]interface{}{"name": "temp.tar", "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
+
+        // Future SDKs may require other unpacking procedures not yet covered here....
+    }
+
+    return nil
 }
 
 func init() {
-	sdkCmd.AddCommand(sdkInstallCmd)
+    sdkCmd.AddCommand(sdkInstallCmd)
+
+    sdkMap = make(map[string]*sdkInfo)
+    sdkMap["docker"] = &sdkInfo{ UrlPath: "blackbox-0.1.0.tar.gz", FileName: "blackbox-0.1.0.tar.gz", isGzTar: true, Unpack: true, UnpackDir: "dockerSkeleton"}
+    sdkMap["ios"] = &sdkInfo{ UrlPath: "OpenWhiskIOSStarterApp.zip", FileName: "OpenWhiskIOSStarterApp.zip", IsZip: true, Unpack: false}
 }
diff --git a/commands/trigger.go b/commands/trigger.go
index 3323caa..31cdb27 100644
--- a/commands/trigger.go
+++ b/commands/trigger.go
@@ -1,271 +1,550 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"strings"
+    "errors"
+    "fmt"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
 
-	"github.com/spf13/cobra"
+    "github.com/spf13/cobra"
+    "github.com/fatih/color"
 )
 
 // triggerCmd represents the trigger command
 var triggerCmd = &cobra.Command{
-	Use:   "trigger",
-	Short: "work with triggers",
+    Use:   "trigger",
+    Short: wski18n.T("work with triggers"),
 }
 
 var triggerFireCmd = &cobra.Command{
-	Use:   "fire <name string> <payload string>",
-	Short: "fire trigger event",
+    Use:   "fire TRIGGER_NAME [PAYLOAD]",
+    Short: wski18n.T("fire trigger event"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var parameters interface{}
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 2, "Trigger fire",
+                wski18n.T("A trigger name is required. A payload is optional.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		var triggerName, payloadArg string
-		if len(args) < 1 || len(args) > 2 {
-			err = errors.New("Invalid argument list")
-			fmt.Println(err)
-			return
-		}
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
 
-		triggerName = args[0]
+            return whiskErr
+        }
 
-		payload := map[string]interface{}{}
+        client.Namespace = qName.namespace
 
-		if len(flags.common.param) > 0 {
-			parameters, err := parseParameters(flags.common.param)
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
+        // Add payload to parameters
+        if len(args) == 2 {
+            flags.common.param = append(flags.common.param, getFormattedJSON("payload", args[1]))
+            flags.common.param = append(flags.common.param, flags.common.param...)
+        }
 
-			for _, param := range parameters {
-				payload[param.Key] = param.Value
-			}
-		}
+        if len(flags.common.param) > 0 {
+            parameters, err = getJSONFromStrings(flags.common.param, false)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, false) failed: %s\n", flags.common.param, err)
+                errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+                        map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
+        }
 
-		if len(args) == 2 {
-			payloadArg = args[1]
-			reader := strings.NewReader(payloadArg)
-			err = json.NewDecoder(reader).Decode(&payload)
-			if err != nil {
-				payload["payload"] = payloadArg
-			}
-		}
+        trigResp, _, err := client.Triggers.Fire(qName.entityName, parameters)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.Fire(%s, %#v) failed: %s\n", qName.entityName, parameters, err)
+            errStr := wski18n.T("Unable to fire trigger '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": qName.entityName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
 
-		_, _, err = client.Triggers.Fire(triggerName, payload)
-
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-
-		fmt.Println("ok: fired trigger")
-	},
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} triggered /{{.namespace}}/{{.name}} with id {{.id}}\n",
+                map[string]interface{}{
+                    "ok": color.GreenString("ok:"),
+                    "namespace": boldString(qName.namespace),
+                    "name": boldString(qName.entityName),
+                    "id": boldString(trigResp.ActivationId)}))
+        return nil
+    },
 }
 
 var triggerCreateCmd = &cobra.Command{
-	Use:   "create",
-	Short: "create new trigger",
+    Use:   "create TRIGGER_NAME",
+    Short: wski18n.T("create new trigger"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var annotations interface{}
+        var feedArgPassed bool = (flags.common.feed != "")
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 1, "Trigger create",
+                wski18n.T("A trigger name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
 
-		triggerName := args[0]
+        client.Namespace = qName.namespace
 
-		parameters, err := parseParameters(flags.common.param)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		annotations, err := parseAnnotations(flags.common.annotation)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        var fullTriggerName string
+        var fullFeedName string
+        if feedArgPassed {
+            whisk.Debug(whisk.DbgInfo, "Trigger has a feed\n")
+            feedqName, err := parseQualifiedName(flags.common.feed)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", flags.common.feed, err)
+                errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                        map[string]interface{}{"name": flags.common.feed, "err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+            if len(feedqName.namespace) == 0 {
+                whisk.Debug(whisk.DbgError, "Namespace is missing from '%s'\n", flags.common.feed)
+                errStr := wski18n.T("No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\"")
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
 
-		trigger := &whisk.Trigger{
-			Name:        triggerName,
-			Parameters:  parameters,
-			Annotations: annotations,
-		}
+            fullFeedName = fmt.Sprintf("/%s/%s", feedqName.namespace, feedqName.entityName)
+            fullTriggerName = fmt.Sprintf("/%s/%s", qName.namespace, qName.entityName)
+            flags.common.param = append(flags.common.param, getFormattedJSON("lifecycleEvent", "CREATE"))
+            flags.common.param = append(flags.common.param, getFormattedJSON("triggerName", fullTriggerName))
+            flags.common.param = append(flags.common.param, getFormattedJSON("authKey", client.Config.AuthToken))
+        }
 
-		trigger, _, err = client.Triggers.Insert(trigger, false)
 
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        // Convert the trigger's list of default parameters from a string into []KeyValue
+        // The 1 or more --param arguments have all been combined into a single []string
+        // e.g.   --p arg1,arg2 --p arg3,arg4   ->  [arg1, arg2, arg3, arg4]
+        whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", flags.common.param)
+        parameters, err := getJSONFromStrings(flags.common.param, !feedArgPassed)
 
-		fmt.Println("ok: created trigger")
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.param, err)
+            errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+                    map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
 
-		printJSON(trigger)
-	},
+        // Add feed to annotations
+        if feedArgPassed {
+            flags.common.annotation = append(flags.common.annotation, getFormattedJSON("feed", flags.common.feed))
+        }
+
+        whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", flags.common.annotation)
+        annotations, err = getJSONFromStrings(flags.common.annotation, true)
+
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.annotation, err)
+            errStr := wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+                    map[string]interface{}{"annotation": fmt.Sprintf("%#v",flags.common.annotation), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
+
+        trigger := &whisk.Trigger{
+            Name:        qName.entityName,
+            Annotations: annotations.(whisk.KeyValueArr),
+        }
+
+        if !feedArgPassed {
+            trigger.Parameters = parameters.(whisk.KeyValueArr)
+        }
+
+        _, _, err = client.Triggers.Insert(trigger, false)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.Insert(%+v,false) failed: %s\n", trigger, err)
+            errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": trigger.Name, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        // Invoke the specified feed action to configure the trigger feed
+        if feedArgPassed {
+            err := configureFeed(trigger.Name, fullFeedName)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", trigger.Name, flags.common.feed,
+                    err)
+                errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.err}}",
+                        map[string]interface{}{"name": trigger.Name, "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+
+                // Delete trigger that was created for this feed
+                delerr := deleteTrigger(args[0])
+                if delerr != nil {
+                    whisk.Debug(whisk.DbgWarn, "Ignoring deleteTrigger(%s) failure: %s\n", args[0], delerr)
+                }
+                return werr
+            }
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} created trigger {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)}))
+        return nil
+    },
 }
 
 var triggerUpdateCmd = &cobra.Command{
-	Use:   "update",
-	Short: "update existing trigger",
+    Use:   "update TRIGGER_NAME",
+    Short: wski18n.T("update an existing trigger, or create a trigger if it does not exist"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
-	Run: func(cmd *cobra.Command, args []string) {
+        if whiskErr := checkArgs(args, 1, 1, "Trigger update",
+                wski18n.T("A trigger name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
 
-		triggerName := args[0]
-		parameters, err := parseParameters(flags.common.param)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		annotations, err := parseAnnotations(flags.common.annotation)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+            return whiskErr
+        }
 
-		trigger := &whisk.Trigger{
-			Name:        triggerName,
-			Parameters:  parameters,
-			Annotations: annotations,
-		}
+        client.Namespace = qName.namespace
 
-		trigger, _, err = client.Triggers.Insert(trigger, true)
+        // Convert the trigger's list of default parameters from a string into []KeyValue
+        // The 1 or more --param arguments have all been combined into a single []string
+        // e.g.   --p arg1,arg2 --p arg3,arg4   ->  [arg1, arg2, arg3, arg4]
 
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
+        whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", flags.common.param)
+        parameters, err := getJSONFromStrings(flags.common.param, true)
 
-		fmt.Println("ok: updated trigger")
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.param, err)
+            errStr := wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+                    map[string]interface{}{"param": fmt.Sprintf("%#v",flags.common.param), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
 
-		printJSON(trigger)
-	},
+        whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", flags.common.annotation)
+        annotations, err := getJSONFromStrings(flags.common.annotation, true)
+
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, true) failed: %s\n", flags.common.annotation, err)
+            errStr := wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+                    map[string]interface{}{"annotation": fmt.Sprintf("%#v",flags.common.annotation), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return werr
+        }
+
+        trigger := &whisk.Trigger{
+            Name:        qName.entityName,
+            Parameters:  parameters.(whisk.KeyValueArr),
+            Annotations: annotations.(whisk.KeyValueArr),
+        }
+
+        _, _, err = client.Triggers.Insert(trigger, true)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err)
+            errStr := wski18n.T("Unable to update trigger '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": trigger.Name, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} updated trigger {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)}))
+        return nil
+    },
 }
 
 var triggerGetCmd = &cobra.Command{
-	Use:   "get",
-	Short: "get trigger",
+    Use:   "get TRIGGER_NAME [FIELD_FILTER]",
+    Short: wski18n.T("get trigger"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var field string
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 2, "Trigger get", wski18n.T("A trigger name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		triggerName := args[0]
+        if len(args) > 1 {
+            field = args[1]
 
-		trigger, _, err := client.Triggers.Get(triggerName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Println("ok: got trigger ", triggerName)
-		printJSON(trigger)
-	},
+            if !fieldExists(&whisk.Trigger{}, field) {
+                errMsg := wski18n.T("Invalid field filter '{{.arg}}'.", map[string]interface{}{"arg": field})
+                whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+
+            return whiskErr
+        }
+
+        client.Namespace = qName.namespace
+
+        retTrigger, _, err := client.Triggers.Get(qName.entityName)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.Get(%s) failed: %s\n", qName.entityName, err)
+            errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": qName.entityName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        if (flags.trigger.summary) {
+            printSummary(retTrigger)
+        } else {
+            if len(field) > 0 {
+                fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got trigger {{.name}}, displaying field {{.field}}\n",
+                    map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName),
+                    "field": boldString(field)}))
+                printField(retTrigger, field)
+            } else {
+                fmt.Fprintf(color.Output, wski18n.T("{{.ok}} got trigger {{.name}}\n",
+                        map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName)}))
+                printJSON(retTrigger)
+            }
+        }
+
+        return nil
+    },
 }
 
 var triggerDeleteCmd = &cobra.Command{
-	Use:   "delete <name string>",
-	Short: "delete trigger",
+    Use:   "delete TRIGGER_NAME",
+    Short: wski18n.T("delete trigger"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var retTrigger *whisk.Trigger
+        var fullFeedName string
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		if len(args) != 1 {
-			err = errors.New("Invalid argument")
-			fmt.Println(err)
-			return
-		}
+        if whiskErr := checkArgs(args, 1, 1, "Trigger delete",
+                wski18n.T("A trigger name is required.")); whiskErr != nil {
+            return whiskErr
+        }
 
-		ruleName := args[0]
+        qName, err := parseQualifiedName(args[0])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                    map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
 
-		_, err = client.Triggers.Delete(ruleName)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Println("ok: deleted rule ", ruleName)
-	},
+            return whiskErr
+        }
+
+        client.Namespace = qName.namespace
+
+        retTrigger, _, err = client.Triggers.Delete(qName.entityName)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.Delete(%s) failed: %s\n", qName.entityName, err)
+            errStr := wski18n.T("Unable to delete trigger '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": qName.entityName, "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        // Get full feed name from trigger delete request as it is needed to delete the feed
+        if retTrigger != nil && retTrigger.Annotations != nil {
+            fullFeedName = getValueString(retTrigger.Annotations, "feed")
+
+            if len(fullFeedName) > 0 {
+                fullTriggerName := fmt.Sprintf("/%s/%s", qName.namespace, qName.entityName)
+                flags.common.param = append(flags.common.param, getFormattedJSON("lifecycleEvent", "DELETE"))
+                flags.common.param = append(flags.common.param, getFormattedJSON("triggerName", fullTriggerName))
+                flags.common.param = append(flags.common.param, getFormattedJSON("authKey", client.Config.AuthToken))
+
+                err = configureFeed(qName.entityName, fullFeedName)
+                if err != nil {
+                    whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", qName.entityName, flags.common.feed,
+                        err)
+                    errStr := wski18n.T("Unable to delete trigger '{{.name}}': {{.err}}",
+                            map[string]interface{}{"name": qName.entityName, "err": err})
+                    werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+
+                    return werr
+                }
+            }
+        }
+
+        fmt.Fprintf(color.Output,
+            wski18n.T("{{.ok}} deleted trigger {{.name}}\n",
+                map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qName.entityName)}))
+        return nil
+    },
 }
 
 var triggerListCmd = &cobra.Command{
-	Use:   "list <namespace string>",
-	Short: "list all triggers",
+    Use:   "list [NAMESPACE]",
+    Short: wski18n.T("list all triggers"),
+    SilenceUsage:   true,
+    SilenceErrors:  true,
+    PreRunE: setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        qName := QualifiedName{}
+        if len(args) == 1 {
+            qName, err = parseQualifiedName(args[0])
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[0], err)
+                errStr := wski18n.T("'{{.name}}' is not a valid qualified name: {{.err}}",
+                        map[string]interface{}{"name": args[0], "err": err})
+                werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
+            ns := qName.namespace
+            if len(ns) == 0 {
+                whisk.Debug(whisk.DbgError, "Namespace is missing from '%s'\n", args[0])
+                errStr := wski18n.T("No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\"")
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return werr
+            }
+            client.Namespace = ns
+            whisk.Debug(whisk.DbgInfo, "Using namespace '%s' from argument '%s''\n", ns, args[0])
+        } else if whiskErr := checkArgs(args, 0, 1, "Trigger list",
+                wski18n.T("An optional namespace is the only valid argument.")); whiskErr != nil {
+            return whiskErr
+        }
 
-	Run: func(cmd *cobra.Command, args []string) {
-		var err error
-		qName := qualifiedName{}
-		if len(args) == 1 {
-			qName, err = parseQualifiedName(args[0])
-			if err != nil {
-				fmt.Printf("error: %s", err)
-				return
-			}
-			ns := qName.namespace
-			if len(ns) == 0 {
-				err = errors.New("No valid namespace detected.  Make sure that namespace argument is preceded by a \"/\"")
-				fmt.Printf("error: %s\n", err)
-				return
-			}
+        options := &whisk.TriggerListOptions{
+            Skip:  flags.common.skip,
+            Limit: flags.common.limit,
+        }
+        triggers, _, err := client.Triggers.List(options)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Triggers.List(%#v) for namespace '%s' failed: %s\n", options,
+                client.Namespace, err)
+            errStr := wski18n.T("Unable to obtain the list of triggers for namespace '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": getClientNamespace(), "err": err})
+            werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+        printList(triggers)
+        return nil
+    },
+}
 
-			client.Namespace = ns
+func configureFeed(triggerName string, FullFeedName string) error {
+    feedArgs := []string {FullFeedName}
+    flags.common.blocking = true
+    err := actionInvokeCmd.RunE(nil, feedArgs)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "Invoke of action '%s' failed: %s\n", FullFeedName, err)
+        errStr := wski18n.T("Unable to invoke trigger '{{.trigname}}' feed action '{{.feedname}}'; feed is not configured: {{.err}}",
+                map[string]interface{}{"trigname": triggerName, "feedname": FullFeedName, "err": err})
+        err = whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+    } else {
+        whisk.Debug(whisk.DbgInfo, "Successfully configured trigger feed via feed action '%s'\n", FullFeedName)
+    }
 
-			if pkg := qName.packageName; len(pkg) > 0 {
-				// todo :: scope call to package
-			}
-		}
+    return err
+}
 
-		options := &whisk.TriggerListOptions{
-			Skip:  flags.common.skip,
-			Limit: flags.common.limit,
-		}
-		triggers, _, err := client.Triggers.List(options)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		fmt.Println(triggers)
-		printJSON(triggers)
-	},
+func deleteTrigger(triggerName string) error {
+    args := []string {triggerName}
+    err := triggerDeleteCmd.RunE(nil, args)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "Trigger '%s' delete failed: %s\n", triggerName, err)
+        errStr := wski18n.T("Unable to delete trigger '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": triggerName, "err": err})
+        err = whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+    }
+
+    return err
 }
 
 func init() {
+    triggerCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+    triggerCreateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+    triggerCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+    triggerCreateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
+    triggerCreateCmd.Flags().StringVarP(&flags.common.feed, "feed", "f", "", wski18n.T("trigger feed `ACTION_NAME`"))
 
-	triggerCreateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	triggerCreateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
-	triggerCreateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
+    triggerUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
+    triggerUpdateCmd.Flags().StringVarP(&flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
+    triggerUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+    triggerUpdateCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
 
-	triggerUpdateCmd.Flags().StringSliceVarP(&flags.common.annotation, "annotation", "a", []string{}, "annotations")
-	triggerUpdateCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
-	triggerUpdateCmd.Flags().BoolVar(&flags.common.shared, "shared", false, "shared action (default: private)")
+    triggerGetCmd.Flags().BoolVarP(&flags.trigger.summary, "summary", "s", false, wski18n.T("summarize trigger details"))
 
-	triggerFireCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, "default parameters")
+    triggerFireCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
+    triggerFireCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
 
-	triggerListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, "skip this many entities from the head of the collection")
-	triggerListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 0, "only return this many entities from the collection")
+    triggerListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of triggers from the result"))
+    triggerListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of triggers from the collection"))
 
-	triggerCmd.AddCommand(
-		triggerFireCmd,
-		triggerCreateCmd,
-		triggerUpdateCmd,
-		triggerGetCmd,
-		triggerDeleteCmd,
-		triggerListCmd,
-	)
+    triggerCmd.AddCommand(
+        triggerFireCmd,
+        triggerCreateCmd,
+        triggerUpdateCmd,
+        triggerGetCmd,
+        triggerDeleteCmd,
+        triggerListCmd,
+    )
 
 }
diff --git a/commands/util.go b/commands/util.go
index 829f7d4..ccabcd1 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -1,231 +1,1070 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
 import (
-	"errors"
-	"fmt"
-	"strings"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk/whisk"
+    "bufio"
+    "errors"
+    "fmt"
+    "strings"
 
-	"github.com/fatih/color"
-	prettyjson "github.com/hokaccha/go-prettyjson"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
+
+    "github.com/fatih/color"
+    //prettyjson "github.com/hokaccha/go-prettyjson"  // See prettyjson comment below
+    "archive/tar"
+    "io"
+    "os"
+    "compress/gzip"
+    "archive/zip"
+    "encoding/json"
+    "net/url"
+    "io/ioutil"
+    "sort"
+    "reflect"
+    "bytes"
 )
 
-type qualifiedName struct {
-	namespace   string
-	packageName string
-	entityName  string
+type QualifiedName struct {
+    namespace   string  // namespace. does not include leading '/'.  may be "" (i.e. default namespace)
+    packageName string  // package.  may be "".  does not include leading/trailing '/'
+    entity      string  // entity.  should not be ""
+    entityName  string  // pkg+entity
 }
 
-func (qName qualifiedName) String() string {
-	output := []string{}
-	if len(qName.namespace) > 0 {
-		output = append(output, "/", qName.namespace, "/")
-	}
-	if len(qName.packageName) > 0 {
-		output = append(output, qName.packageName, "/")
-	}
-	output = append(output, qName.entityName)
+func (qName QualifiedName) String() string {
+    output := []string{}
 
-	return strings.Join(output, "")
+    if len(qName.namespace) > 0 {
+        output = append(output, "/", qName.namespace, "/")
+    }
+    if len(qName.packageName) > 0 {
+        output = append(output, qName.packageName, "/")
+    }
+    output = append(output, qName.entityName)
+
+    return strings.Join(output, "")
 }
 
-func parseQualifiedName(name string) (qName qualifiedName, err error) {
-	if len(name) == 0 {
-		err = errors.New("Invalid name format")
-		return
-	}
-	if name[:1] == "/" {
-		name = name[1:]
-		i := strings.Index(name, "/")
-		if i == -1 {
-			qName.namespace = name
-			return
-		}
-		if i == 0 {
-			err = errors.New("Invalid name format")
-			return
-		}
+/*
+Parse a (possibly fully qualified) resource name into namespace and name components. If the given qualified name isNone,
+then this is a default qualified name and it is resolved from properties. If the namespace is missing from the qualified
+name, the namespace is also resolved from the property file.
 
-		qName.namespace = name[:i]
-		name = name[i+1:]
-	}
+Return a qualifiedName struct
 
-	i := strings.Index(name, "/")
+Examples:
+      foo => qName {namespace: "_", entityName: foo}
+      pkg/foo => qName {namespace: "_", entityName: pkg/foo}
+      /ns/foo => qName {namespace: ns, entityName: foo}
+      /ns/pkg/foo => qName {namespace: ns, entityName: pkg/foo}
+*/
+func parseQualifiedName(name string) (QualifiedName, error) {
+    var qualifiedName QualifiedName
 
-	if i > 0 {
-		qName.packageName = name[:i]
-		name = name[i+1:]
-	}
+    // If name has a preceding delimiter (/), it contains a namespace. Otherwise the name does not specify a namespace,
+    // so default the namespace to the namespace value set in the properties file; if that is not set, use "_"
+    if  strings.HasPrefix(name, "/")  {
+        parts := strings.Split(name, "/")
+        qualifiedName.namespace = parts[1]
 
-	qName.entityName = name
+        if len(parts) < 2 || len(parts) > 4 {
+            whisk.Debug(whisk.DbgError, "A valid qualified name was not detected\n")
+            errStr := wski18n.T("A valid qualified name must be specified.")
+            err := whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return qualifiedName, err
+        }
 
-	return
+        for i := 1; i < len(parts); i++ {
+            if len(parts[i]) == 0 || parts[i] == "." {
+                whisk.Debug(whisk.DbgError, "A valid qualified name was not detected\n")
+                errStr := wski18n.T("A valid qualified name must be specified.")
+                err := whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return qualifiedName, err
+            }
+        }
 
+        qualifiedName.entityName = strings.Join(parts[2:], "/")
+        if len(parts) == 4 {
+            qualifiedName.packageName = parts[2]
+        }
+        qualifiedName.entity = parts[len(parts)-1]
+    } else {
+        if len(name) == 0 || name == "." {
+            whisk.Debug(whisk.DbgError, "A valid qualified name was not detected\n")
+            errStr := wski18n.T("A valid qualified name must be specified.")
+            err := whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return qualifiedName, err
+        }
+
+        parts := strings.Split(name, "/")
+        qualifiedName.entity = parts[len(parts)-1]
+        if len(parts) == 2 {
+            qualifiedName.packageName = parts[0]
+        }
+        qualifiedName.entityName = name
+        qualifiedName.namespace = getNamespace()
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Qualified pkg+entity (EntityName): %s\n", qualifiedName.entityName)
+    whisk.Debug(whisk.DbgInfo, "Qualified namespace: %s\n", qualifiedName.namespace)
+    whisk.Debug(whisk.DbgInfo, "Qualified package: %s\n", qualifiedName.packageName)
+    whisk.Debug(whisk.DbgInfo, "Qualified entity: %s\n", qualifiedName.entity)
+
+    return qualifiedName, nil
 }
 
-func parseKeyValueArray(args []string) ([]whisk.KeyValue, error) {
-	parsed := []whisk.KeyValue{}
-	if len(args)%2 != 0 {
-		err := errors.New("key|value arguments must be submitted in comma-separated pairs")
-		return parsed, err
-	}
+func getNamespace() (string) {
+    namespace := "_"
 
-	for i := 0; i < len(args); i += 2 {
-		keyValue := whisk.KeyValue{
-			Key:   args[i],
-			Value: args[i+1],
-		}
-		parsed = append(parsed, keyValue)
+    if Properties.Namespace != "" {
+        namespace = Properties.Namespace
+    }
 
-	}
-	return parsed, nil
+    return namespace
 }
 
-func parseParameters(args []string) (whisk.Parameters, error) {
-	parameters := whisk.Parameters{}
-	parsedArgs, err := parseKeyValueArray(args)
-	if err != nil {
-		return parameters, err
-	}
-	parameters = whisk.Parameters(parsedArgs)
-	return parameters, nil
+/*
+Return a fully qualified name given a (possibly fully qualified) resource name and optional namespace.
+
+Examples:
+      (foo, None) => /_/foo
+      (pkg/foo, None) => /_/pkg/foo
+      (foo, ns) => /ns/foo
+      (/ns/pkg/foo, None) => /ns/pkg/foo
+      (/ns/pkg/foo, otherns) => /ns/pkg/foo
+*/
+func getQualifiedName(name string, namespace string) (string) {
+    if strings.HasPrefix(name, "/") {
+        return name
+    } else if strings.HasPrefix(namespace, "/")  {
+        return fmt.Sprintf("%s/%s", namespace, name)
+    } else {
+        if len(namespace) == 0 {
+            namespace = Properties.Namespace
+        }
+        return fmt.Sprintf("/%s/%s", namespace, name)
+    }
 }
 
-func parseAnnotations(args []string) (whisk.Annotations, error) {
-	annotations := whisk.Annotations{}
-	parsedArgs, err := parseKeyValueArray(args)
-	if err != nil {
-		return annotations, err
-	}
-	annotations = whisk.Annotations(parsedArgs)
-	return annotations, nil
+func csvToQualifiedActions(artifacts string) ([]string) {
+    var res []string
+    actions := strings.Split(artifacts, ",")
+    for i := 0; i < len(actions); i++ {
+        res = append(res, getQualifiedName(actions[i], Properties.Namespace))
+    }
+
+    return res
+}
+
+func getJSONFromStrings(content []string, keyValueFormat bool) (interface{}, error) {
+    var data map[string]interface{}
+    var res interface{}
+
+    whisk.Debug(whisk.DbgInfo, "Convert content to JSON: %#v\n", content)
+
+    for i := 0; i < len(content); i++ {
+        dc := json.NewDecoder(strings.NewReader(content[i]))
+        dc.UseNumber()
+        if err := dc.Decode(&data); err!=nil {
+            whisk.Debug(whisk.DbgError, "Invalid JSON detected for '%s' \n", content[i])
+            return whisk.KeyValueArr{} , err
+        }
+
+        whisk.Debug(whisk.DbgInfo, "Created map '%v' from '%v'\n", data, content[i])
+    }
+
+    if keyValueFormat {
+        res = getKeyValueFormattedJSON(data)
+    } else {
+        res = data
+    }
+
+    return res, nil
+}
+
+func getKeyValueFormattedJSON(data map[string]interface{}) (whisk.KeyValueArr) {
+    var keyValueArr whisk.KeyValueArr
+
+    for key, value := range data {
+        keyValue := whisk.KeyValue{
+            Key:  key,
+            Value: value,
+        }
+        keyValueArr = append(keyValueArr, keyValue)
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Created key/value format '%v' from '%v'\n", keyValueArr, data)
+
+    return keyValueArr
+}
+
+func getFormattedJSON(key string, value string) (string) {
+    var res string
+
+    key = getEscapedJSON(key)
+
+    if isValidJSON(value) {
+        whisk.Debug(whisk.DbgInfo, "Value '%s' is valid JSON.\n", value)
+        res = fmt.Sprintf("{\"%s\": %s}", key, value)
+    } else {
+        whisk.Debug(whisk.DbgInfo, "Converting value '%s' to a string as it is not valid JSON.\n", value)
+        res = fmt.Sprintf("{\"%s\": \"%s\"}", key, value)
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Formatted JSON '%s'\n", res)
+
+    return res
+}
+
+func getEscapedJSON(value string) (string) {
+    value = strings.Replace(value, "\\", "\\\\", -1)
+    value = strings.Replace(value, "\"", "\\\"", -1)
+
+    return value
+}
+
+func isValidJSON(value string) (bool) {
+    var jsonInterface interface{}
+    err := json.Unmarshal([]byte(value), &jsonInterface)
+    return err == nil
 }
 
 var boldString = color.New(color.Bold).SprintFunc()
-var boldPrintf = color.New(color.Bold).PrintfFunc()
 
 func printList(collection interface{}) {
-	switch collection := collection.(type) {
-	case []whisk.Action:
-		printActionList(collection)
-	case []whisk.Trigger:
-		printTriggerList(collection)
-	case []whisk.Package:
-		printPackageList(collection)
-	case []whisk.Rule:
-		printRuleList(collection)
-	case []whisk.Namespace:
-		printNamespaceList(collection)
-	case []whisk.Activation:
-		printActivationList(collection)
-	}
+    switch collection := collection.(type) {
+    case []whisk.Action:
+        printActionList(collection)
+    case []whisk.Trigger:
+        printTriggerList(collection)
+    case []whisk.Package:
+        printPackageList(collection)
+    case []whisk.Rule:
+        printRuleList(collection)
+    case []whisk.Namespace:
+        printNamespaceList(collection)
+    case []whisk.Activation:
+        printActivationList(collection)
+    case []whisk.Api:
+        printApiList(collection)
+    }
+}
+
+func printFullList(collection interface{}) {
+    switch collection := collection.(type) {
+    case []whisk.Action:
+
+    case []whisk.Trigger:
+
+    case []whisk.Package:
+
+    case []whisk.Rule:
+
+    case []whisk.Namespace:
+
+    case []whisk.Activation:
+        printFullActivationList(collection)
+    }
+}
+
+func printSummary(collection interface{}) {
+    switch collection := collection.(type) {
+    case *whisk.Action:
+        printActionSummary(collection)
+    case *whisk.Trigger:
+        printTriggerSummary(collection)
+    case *whisk.Package:
+        printPackageSummary(collection)
+    case *whisk.Rule:
+
+    case *whisk.Namespace:
+
+    case *whisk.Activation:
+    }
 }
 
 func printActionList(actions []whisk.Action) {
-	boldPrintf("actions\n")
-	for _, action := range actions {
-		publishState := "private"
-		if action.Publish {
-			publishState = "shared"
-		}
-		fmt.Printf("%-70s%s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("actions"))
+    for _, action := range actions {
+        publishState := wski18n.T("private")
+        kind := getValueString(action.Annotations, "exec")
+        fmt.Printf("%-70s %s %s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState, kind)
+    }
 }
 
 func printTriggerList(triggers []whisk.Trigger) {
-	boldPrintf("triggers\n")
-	for _, trigger := range triggers {
-		publishState := "private"
-		if trigger.Publish {
-			publishState = "shared"
-		}
-		fmt.Printf("%-70s%s\n", fmt.Sprintf("/%s/%s", trigger.Namespace, trigger.Name), publishState)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("triggers"))
+    for _, trigger := range triggers {
+        publishState := wski18n.T("private")
+        fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", trigger.Namespace, trigger.Name), publishState)
+    }
 }
 
 func printPackageList(packages []whisk.Package) {
-	boldPrintf("packages\n")
-	for _, xPackage := range packages {
-		publishState := "private"
-		if xPackage.Publish {
-			publishState = "shared"
-		}
-		fmt.Printf("%-70s%s\n", fmt.Sprintf("/%s/%s", xPackage.Namespace, xPackage.Name), publishState)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("packages"))
+    for _, xPackage := range packages {
+        publishState := wski18n.T("private")
+        if xPackage.Publish != nil && *xPackage.Publish {
+            publishState = wski18n.T("shared")
+        }
+        fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", xPackage.Namespace, xPackage.Name), publishState)
+    }
 }
 
 func printRuleList(rules []whisk.Rule) {
-	boldPrintf("rules\n")
-	for _, rule := range rules {
-		publishState := "private"
-		if rule.Publish {
-			publishState = "shared"
-		}
-		fmt.Printf("%-70s%s\n", fmt.Sprintf("/%s/%s", rule.Namespace, rule.Name), publishState)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("rules"))
+    for _, rule := range rules {
+        publishState := wski18n.T("private")
+        fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", rule.Namespace, rule.Name), publishState)
+    }
 }
 
 func printNamespaceList(namespaces []whisk.Namespace) {
-	boldPrintf("namespaces\n")
-	for _, namespace := range namespaces {
-		fmt.Printf("%s\n", namespace.Name)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("namespaces"))
+    for _, namespace := range namespaces {
+        fmt.Printf("%s\n", namespace.Name)
+    }
 }
 
 func printActivationList(activations []whisk.Activation) {
-	boldPrintf("activations\n")
-	for _, activation := range activations {
-		fmt.Printf("%s%20s\n", activation.ActivationID, activation.Name)
-	}
+    fmt.Fprintf(color.Output, "%s\n", boldString("activations"))
+    for _, activation := range activations {
+        fmt.Printf("%s %-20s\n", activation.ActivationID, activation.Name)
+    }
 }
 
-//
-//
-//
-// func parseParameters(jsonStr string) (whisk.Parameters, error) {
-// 	parameters := whisk.Parameters{}
-// 	if len(jsonStr) == 0 {
-// 		return parameters, nil
-// 	}
-// 	reader := strings.NewReader(jsonStr)
-// 	err := json.NewDecoder(reader).Decode(&parameters)
-// 	if err != nil {
-// 		return nil, err
-// 	}
-// 	return parameters, nil
-// }
-//
-// func parseAnnotations(jsonStr string) (whisk.Annotations, error) {
-// 	annotations := whisk.Annotations{}
-// 	if len(jsonStr) == 0 {
-// 		return annotations, nil
-// 	}
-// 	reader := strings.NewReader(jsonStr)
-// 	err := json.NewDecoder(reader).Decode(&annotations)
-// 	if err != nil {
-// 		return nil, err
-// 	}
-// 	return annotations, nil
-// }
+func printFullActivationList(activations []whisk.Activation) {
+    fmt.Fprintf(color.Output, "%s\n", boldString("activations"))
+    for _, activation := range activations {
+        printJSON(activation)
+    }
+}
+
+func printApiList(apis []whisk.Api) {
+    fmt.Fprintf(color.Output, "%s\n", boldString("apis"))
+    for _, api := range apis {
+        fmt.Printf("%s %20s %20s\n", api.ApiName, api.GatewayBasePath, api.GatewayFullPath)
+    }
+}
+
+func printFullApiList(apis []whisk.Api) {
+    fmt.Fprintf(color.Output, "%s\n", boldString("apis"))
+    for _, api := range apis {
+        printJSON(api)
+    }
+}
+
+func printActivationLogs(logs []string) {
+    for _, log := range logs {
+        fmt.Printf("%s\n", log)
+    }
+}
+
+func printArrayContents(arrStr []string) {
+    for _, str := range arrStr {
+        fmt.Printf("%s\n", str)
+    }
+}
+
+func printPackageSummary(pkg *whisk.Package) {
+    printEntitySummary(fmt.Sprintf("%7s", "package"), getFullName(pkg.Namespace, pkg.Name, ""),
+        getValueString(pkg.Annotations, "description"),
+        strings.Join(getChildValueStrings(pkg.Annotations, "parameters", "name"), ", "))
+
+
+    if pkg.Actions != nil {
+        for _, action := range pkg.Actions {
+            printEntitySummary(fmt.Sprintf("%7s", "action"), getFullName(pkg.Namespace, pkg.Name, action.Name),
+                getValueString(action.Annotations, "description"),
+                strings.Join(getChildValueStrings(action.Annotations, "parameters", "name"), ", "))
+        }
+    }
+
+    if pkg.Feeds != nil {
+        for _, feed := range pkg.Feeds {
+            printEntitySummary(fmt.Sprintf("%7s", "feed  "), getFullName(pkg.Namespace, pkg.Name, feed.Name),
+                getValueString(feed.Annotations, "description"),
+                strings.Join(getChildValueStrings(feed.Annotations, "parameters", "name"), ", "))
+        }
+    }
+}
+
+func printActionSummary(action *whisk.Action) {
+    printEntitySummary(fmt.Sprintf("%6s", "action"),
+        getFullName(action.Namespace, "", action.Name),
+        getValueString(action.Annotations, "description"),
+        strings.Join(getChildValueStrings(action.Annotations, "parameters", "name"), ", "))
+}
+
+func printTriggerSummary(trigger *whisk.Trigger) {
+    printEntitySummary(fmt.Sprintf("%7s", "trigger"),
+        getFullName(trigger.Namespace, "", trigger.Name),
+        getValueString(trigger.Annotations, "description"),
+        strings.Join(getChildValueStrings(trigger.Annotations, "parameters", "name"), ", "))
+}
+
+func printRuleSummary(rule *whisk.Rule) {
+    fmt.Fprintf(color.Output, "%s %s\n", boldString(fmt.Sprintf("%4s", "rule")),
+        getFullName(rule.Namespace, "", rule.Name))
+    fmt.Fprintf(color.Output, "   (%s: %s)\n", boldString(wski18n.T("status")), rule.Status)
+}
+
+func printEntitySummary(entityType string, fullName string, description string, params string) {
+    if len(description) > 0 {
+        fmt.Fprintf(color.Output, "%s %s: %s\n", boldString(entityType), fullName, description)
+    } else {
+        fmt.Fprintf(color.Output, "%s %s\n", boldString(entityType), fullName)
+    }
+
+    if len(params) > 0 {
+        fmt.Fprintf(color.Output, "   (%s: %s)\n", boldString(wski18n.T("parameters")), params)
+    }
+}
+
+func getFullName(namespace string, packageName string, entityName string) (string) {
+    var fullName string
+
+    if len(namespace) > 0 && len(packageName) > 0 && len(entityName) > 0 {
+        fullName = fmt.Sprintf("/%s/%s/%s", namespace, packageName, entityName)
+    } else if len(namespace) > 0 && len(packageName) > 0 {
+        fullName = fmt.Sprintf("/%s/%s", namespace, packageName)
+    } else if len(namespace) > 0 && len(entityName) > 0 {
+        fullName = fmt.Sprintf("/%s/%s", namespace, entityName)
+    } else if len(namespace) > 0 {
+        fullName = fmt.Sprintf("/%s", namespace)
+    }
+
+    return fullName
+}
+
+func deleteKey(key string, keyValueArr whisk.KeyValueArr) (whisk.KeyValueArr) {
+    for i := 0; i < len(keyValueArr); i++ {
+        if keyValueArr[i].Key == key {
+            keyValueArr = append(keyValueArr[:i], keyValueArr[i + 1:]...)
+            break
+        }
+    }
+
+    return keyValueArr
+}
+
+func addKeyValue(key string, value interface{}, keyValueArr whisk.KeyValueArr) (whisk.KeyValueArr) {
+    keyValue := whisk.KeyValue{
+        Key:  key,
+        Value: value,
+    }
+
+    return append(keyValueArr, keyValue)
+}
+
+func getKeys(keyValueArr whisk.KeyValueArr) ([]string) {
+    var res []string
+
+    for i := 0; i < len(keyValueArr); i++ {
+        res = append(res, keyValueArr[i].Key)
+    }
+
+    sort.Strings(res)
+    whisk.Debug(whisk.DbgInfo, "Got keys '%v' from '%v'\n", res, keyValueArr)
+
+    return res
+}
+
+func getValue(keyValueArr whisk.KeyValueArr, key string) (interface{}) {
+    var res interface{}
+
+    for i := 0; i < len(keyValueArr); i++ {
+        if keyValueArr[i].Key == key {
+            res = keyValueArr[i].Value
+            break;
+        }
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Got value '%v' from '%v' for key '%s'\n", res, keyValueArr, key)
+
+    return res
+}
+
+func getValueString(keyValueArr whisk.KeyValueArr, key string) (string) {
+    var value interface{}
+    var res string
+
+    value = getValue(keyValueArr, key)
+    castedValue, canCast := value.(string)
+
+    if (canCast) {
+        res = castedValue
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Got string value '%v' for key '%s'\n", res, key)
+
+    return res
+}
+
+func getChildValues(keyValueArr whisk.KeyValueArr, key string, childKey string) ([]interface{}) {
+    var value interface{}
+    var res []interface{}
+
+    value = getValue(keyValueArr, key)
+
+    castedValue, canCast := value.([]interface{})
+    if canCast {
+        for i := 0; i < len(castedValue); i++ {
+            castedValue, canCast := castedValue[i].(map[string]interface{})
+            if canCast {
+                for subKey, subValue := range castedValue {
+                    if subKey == childKey {
+                        res = append(res, subValue)
+                    }
+                }
+            }
+        }
+    }
+
+    whisk.Debug(whisk.DbgInfo, "Got values '%s' from '%v' for key '%s' and child key '%s'\n", res, keyValueArr, key,
+        childKey)
+
+    return res
+}
+
+func getChildValueStrings(keyValueArr whisk.KeyValueArr, key string, childKey string) ([]string) {
+    var keys []interface{}
+    var res []string
+
+    keys = getChildValues(keyValueArr, key, childKey)
+
+    for i := 0; i < len(keys); i++ {
+        castedValue, canCast := keys[i].(string)
+        if (canCast) {
+            res = append(res, castedValue)
+        }
+    }
+
+    sort.Strings(res)
+    whisk.Debug(whisk.DbgInfo, "Got values '%s' from '%v' for key '%s' and child key '%s'\n", res, keyValueArr, key,
+        childKey)
+
+    return res
+}
+
+func getValueFromJSONResponse(field string, response map[string]interface {}) (interface{}) {
+    var res interface{}
+
+    for key, value := range response {
+        if key == field {
+            res = value
+            break
+        }
+    }
+
+    return res
+}
 
 func logoText() string {
+    logo := `
+        ____      ___                   _    _ _     _     _
+       /\   \    / _ \ _ __   ___ _ __ | |  | | |__ (_)___| | __
+  /\  /__\   \  | | | | '_ \ / _ \ '_ \| |  | | '_ \| / __| |/ /
+ /  \____ \  /  | |_| | |_) |  __/ | | | |/\| | | | | \__ \   <
+ \   \  /  \/    \___/| .__/ \___|_| |_|__/\__|_| |_|_|___/_|\_\
+  \___\/ tm           |_|
+`
 
-	logo := `
-
-__          ___     _     _
-\ \        / / |   (_)   | |
- \ \  /\  / /| |__  _ ___| | __
-  \ \/  \/ / | '_ \| / __| |/ /
-   \  /\  /  | | | | \__ \   <
-    \/  \/   |_| |_|_|___/_|\_\
-
-			`
-
-	return logo
+    return logo
 }
 
-func printJSON(v interface{}) {
-	output, _ := prettyjson.Marshal(v)
-	fmt.Println(string(output))
+func printJSON(v interface{}, stream ...io.Writer) {
+    // Can't use prettyjson util issue  https://github.com/hokaccha/go-prettyjson/issues/1 is fixed
+    //output, _ := prettyjson.Marshal(v)
+    //
+    //if len(stream) > 0 {
+    //    fmt.Fprintf(stream[0], string(output))
+    //} else {
+    //    fmt.Fprintf(color.Output, string(output))
+    //}
+    printJsonNoColor(v, stream...)
+}
+
+func printJsonNoColor(decoded interface{}, stream ...io.Writer) {
+    var output bytes.Buffer
+
+    buffer := new(bytes.Buffer)
+    encoder := json.NewEncoder(buffer)
+    encoder.SetEscapeHTML(false)
+    encoder.Encode(&decoded)
+    json.Indent(&output, buffer.Bytes(), "", "    ")
+
+    if len(stream) > 0 {
+        fmt.Fprintf(stream[0], "%s", string(output.Bytes()))
+    } else {
+        fmt.Fprintf(os.Stdout, "%s", string(output.Bytes()))
+    }
+}
+
+func unpackGzip(inpath string, outpath string) error {
+    // Make sure the target file does not exist
+    if _, err := os.Stat(outpath); err == nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' exists\n", outpath)
+        errStr := wski18n.T("The file {{.name}} already exists.  Delete it and retry.",
+            map[string]interface{}{"name": outpath})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    // Make sure the input file exists
+    if _, err := os.Stat(inpath); err != nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' does not exist\n", inpath)
+        errStr := wski18n.T("The file '{{.name}}' does not exist.", map[string]interface{}{"name": inpath})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    unGzFile, err := os.Create(outpath)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", outpath, err)
+        errStr := wski18n.T("Error creating unGzip file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": outpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+    defer unGzFile.Close()
+
+    gzFile, err := os.Open(inpath)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Open(%s) failed: %s\n", inpath, err)
+        errStr := wski18n.T("Error opening Gzip file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": inpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+    defer gzFile.Close()
+
+    gzReader, err := gzip.NewReader(gzFile)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "gzip.NewReader() failed: %s\n", err)
+        errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": inpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    _, err = io.Copy(unGzFile, gzReader)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "io.Copy() failed: %s\n", err)
+        errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": inpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    return nil
+}
+
+func unpackZip(inpath string) error {
+    // Make sure the input file exists
+    if _, err := os.Stat(inpath); err != nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' does not exist\n", inpath)
+        errStr := wski18n.T("The file '{{.name}}' does not exist.", map[string]interface{}{"name": inpath})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    zipFileReader, err := zip.OpenReader(inpath)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "zip.OpenReader(%s) failed: %s\n", inpath, err)
+        errStr := wski18n.T("Unable to opens '{{.name}}' for unzipping: {{.err}}",
+            map[string]interface{}{"name": inpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+    defer zipFileReader.Close()
+
+    // Loop through the files in the zipfile
+    for _, item := range zipFileReader.File {
+        itemName := item.Name
+        itemType := item.Mode()
+
+        whisk.Debug(whisk.DbgInfo, "file item - %#v\n", item)
+
+        if itemType.IsDir() {
+            if err := os.MkdirAll(item.Name, item.Mode()); err != nil {
+                whisk.Debug(whisk.DbgError, "os.MkdirAll(%s, %d) failed: %s\n", item.Name, item.Mode(), err)
+                errStr := wski18n.T("Unable to create directory '{{.dir}}' while unzipping '{{.name}}': {{.err}}",
+                        map[string]interface{}{"dir": item.Name, "name": inpath, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
+
+        if itemType.IsRegular() {
+            unzipFile, err := item.Open()
+            defer unzipFile.Close()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "'%s' Open() failed: %s\n", item.Name, err)
+                errStr := wski18n.T("Unable to open zipped file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
+                        map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            targetFile, err := os.Create(itemName)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", itemName, err)
+                errStr := wski18n.T("Unable to create file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
+                        map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            if _, err := io.Copy(targetFile, unzipFile); err != nil {
+                whisk.Debug(whisk.DbgError, "io.Copy() of '%s' failed: %s\n", itemName, err)
+                errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
+                        map[string]interface{}{"name": itemName, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        }
+    }
+
+    return nil
+}
+
+func unpackTar(inpath string) error {
+
+    // Make sure the input file exists
+    if _, err := os.Stat(inpath); err != nil {
+        whisk.Debug(whisk.DbgError, "os.Stat reports file '%s' does not exist\n", inpath)
+        errStr := wski18n.T("The file '{{.name}}' does not exist.", map[string]interface{}{"name": inpath})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+
+    tarFileReader, err := os.Open(inpath)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Open(%s) failed: %s\n", inpath, err)
+        errStr := wski18n.T("Error opening tar file '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": inpath, "err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+    defer tarFileReader.Close()
+
+    // Loop through the files in the tarfile
+    tReader := tar.NewReader(tarFileReader)
+    for {
+        item, err := tReader.Next()
+        if err == io.EOF {
+            whisk.Debug(whisk.DbgError, "EOF reach during untar\n")
+            break  // end of tar
+        }
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "tReader.Next() failed: %s\n", err)
+            errStr := wski18n.T("Error reading tar file '{{.name}}': {{.err}}",
+                    map[string]interface{}{"name": inpath, "err": err})
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+
+        whisk.Debug(whisk.DbgInfo, "tar file item - %#v\n", item)
+        switch item.Typeflag {
+        case tar.TypeDir:
+            if err := os.MkdirAll(item.Name, os.FileMode(item.Mode)); err != nil {
+                whisk.Debug(whisk.DbgError, "os.MkdirAll(%s, %d) failed: %s\n", item.Name, item.Mode, err)
+                errStr := wski18n.T("Unable to create directory '{{.dir}}' while untarring '{{.name}}': {{.err}}",
+                        map[string]interface{}{"dir": item.Name, "name": inpath, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        case tar.TypeReg:
+            untarFile, err:= os.OpenFile(item.Name, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.FileMode(item.Mode))
+            defer untarFile.Close()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", item.Name, err)
+                errStr := wski18n.T("Unable to create file '{{.file}}' while untarring '{{.name}}': {{.err}}",
+                        map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+            if _, err := io.Copy(untarFile, tReader); err != nil {
+                whisk.Debug(whisk.DbgError, "io.Copy() of '%s' failed: %s\n", item.Name, err)
+                errStr := wski18n.T("Unable to untar file '{{.name}}': {{.err}}",
+                        map[string]interface{}{"name": item.Name, "err": err})
+                werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return werr
+            }
+        default:
+            whisk.Debug(whisk.DbgError, "Unexpected tar file type of %q\n", item.Typeflag)
+            errStr := wski18n.T("Unable to untar '{{.name}}' due to unexpected tar file type\n",
+                    map[string]interface{}{"name": item.Name})
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+    }
+    return nil
+}
+
+func checkArgs(args []string, minimumArgNumber int, maximumArgNumber int, commandName string,
+    requiredArgMsg string) (*whisk.WskError) {
+        exactlyOrAtLeast := wski18n.T("exactly")
+        exactlyOrNoMoreThan := wski18n.T("exactly")
+
+    if (minimumArgNumber != maximumArgNumber) {
+        exactlyOrAtLeast = wski18n.T("at least")
+        exactlyOrNoMoreThan = wski18n.T("no more than")
+    }
+
+    if len(args) < minimumArgNumber {
+        whisk.Debug(whisk.DbgError, fmt.Sprintf("%s command must have %s %d argument(s)\n", commandName,
+            exactlyOrAtLeast, minimumArgNumber))
+        errMsg := wski18n.T("Invalid argument(s). {{.required}}", map[string]interface{}{"required": requiredArgMsg})
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr
+    } else if len(args) > maximumArgNumber {
+        whisk.Debug(whisk.DbgError, fmt.Sprintf("%s command must have %s %d argument(s)\n", commandName,
+            exactlyOrNoMoreThan, maximumArgNumber))
+        errMsg := wski18n.T("Invalid argument(s): {{.args}}. {{.required}}",
+            map[string]interface{}{"args": strings.Join(args[maximumArgNumber:], ", "), "required": requiredArgMsg})
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr
+    } else {
+        return nil
+    }
+}
+
+func getURLBase(host string, path string) (*url.URL, error)  {
+    if len(host) == 0 {
+        errMsg := wski18n.T("An API host must be provided.")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    urlBase := fmt.Sprintf("%s%s", host, path)
+    url, err := url.Parse(urlBase)
+
+    if len(url.Scheme) == 0 || len(url.Host) == 0 {
+        urlBase = fmt.Sprintf("https://%s%s", host, path)
+        url, err = url.Parse(urlBase)
+    }
+
+    return url, err
+}
+
+func normalizeNamespace(namespace string) (string) {
+    if (namespace == "_") {
+        namespace = wski18n.T("default")
+    }
+
+    return namespace
+}
+
+func getClientNamespace() (string) {
+    return normalizeNamespace(client.Config.Namespace)
+}
+
+func readFile(filename string) (string, error) {
+    _, err := os.Stat(filename)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Stat(%s) error: %s\n", filename, err)
+        errMsg := wski18n.T("File '{{.name}}' is not a valid file or it does not exist: {{.err}}",
+                map[string]interface{}{"name": filename, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_USAGE,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+
+        return "", whiskErr
+    }
+
+    file, err := ioutil.ReadFile(filename)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.ioutil.ReadFile(%s) error: %s\n", filename, err)
+        errMsg := wski18n.T("Unable to read '{{.name}}': {{.err}}",
+                map[string]interface{}{"name": filename, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return "", whiskErr
+    }
+
+    return string(file), nil
+}
+
+func fieldExists(value interface{}, field string) (bool) {
+    element := reflect.ValueOf(value).Elem()
+
+    for i := 0; i < element.NumField(); i++ {
+        if strings.ToLower(element.Type().Field(i).Name) == strings.ToLower(field) {
+            return true
+        }
+    }
+
+    return false
+}
+
+func printField(value interface{}, field string) {
+    var matchFunc = func(structField string) bool {
+        return strings.ToLower(structField) == strings.ToLower(field)
+    }
+
+    structValue := reflect.ValueOf(value)
+    fieldValue := reflect.Indirect(structValue).FieldByNameFunc(matchFunc)
+
+    printJSON(fieldValue.Interface())
+}
+
+func parseShared(shared string) (bool, bool, error) {
+    var isShared, isSet bool
+
+    if strings.ToLower(shared) == "yes" {
+        isShared = true
+        isSet = true
+    } else if strings.ToLower(shared) == "no" {
+        isShared = false
+        isSet = true
+    } else if len(shared) == 0 {
+        isSet = false
+    } else {
+        whisk.Debug(whisk.DbgError, "Cannot use value '%s' for shared.\n", shared)
+        errMsg := wski18n.T("Cannot use value '{{.arg}}' for shared.", map[string]interface{}{"arg": shared})
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG,
+            whisk.DISPLAY_USAGE)
+        return false, false, whiskErr
+    }
+
+    whisk.Debug(whisk.DbgError, "Sharing is '%t'\n", isShared)
+
+    return isShared, isSet, nil
+}
+
+func max(a int, b int) int {
+    if (a > b) {
+        return a
+    }
+    return b
+}
+
+func min (a int, b int) int {
+    if (a < b) {
+        return a
+    }
+    return b
+}
+
+func readProps(path string) (map[string]string, error) {
+
+    props := map[string]string{}
+
+    file, err := os.Open(path)
+    if err != nil {
+        // If file does not exist, just return props
+        whisk.Debug(whisk.DbgWarn, "Unable to read whisk properties file '%s' (file open error: %s); falling back to default properties\n" ,path, err)
+        return props, nil
+    }
+    defer file.Close()
+
+    lines := []string{}
+    scanner := bufio.NewScanner(file)
+    for scanner.Scan() {
+        lines = append(lines, scanner.Text())
+    }
+
+    props = map[string]string{}
+    for _, line := range lines {
+        kv := strings.Split(line, "=")
+        if len(kv) != 2 {
+            // Invalid format; skip
+            continue
+        }
+        props[kv[0]] = kv[1]
+    }
+
+    return props, nil
+
+}
+
+func writeProps(path string, props map[string]string) error {
+
+    file, err := os.Create(path)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", path, err)
+        errStr := wski18n.T("Whisk properties file write failure: {{.err}}", map[string]interface{}{"err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return werr
+    }
+    defer file.Close()
+
+    writer := bufio.NewWriter(file)
+    defer writer.Flush()
+    for key, value := range props {
+        line := fmt.Sprintf("%s=%s", strings.ToUpper(key), value)
+        _, err = fmt.Fprintln(writer, line)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "fmt.Fprintln() write to '%s' failed: %s\n", path, err)
+            errStr := wski18n.T("Whisk properties file write failure: {{.err}}", map[string]interface{}{"err": err})
+            werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return werr
+        }
+    }
+    return nil
+}
+
+func getSpaceGuid() (string, error) {
+    // get current props
+    props, err := readProps(Properties.PropsFile)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "readProps(%s) failed: %s\n", Properties.PropsFile, err)
+        errStr := wski18n.T("Unable to obtain the `auth` property value: {{.err}}", map[string]interface{}{"err": err})
+        werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+        return "", werr
+    }
+
+    // get the auth key and parse out the space guid
+    if authToken, hasProp := props["AUTH"]; hasProp {
+        spaceGuid := strings.Split(authToken, ":")[0]
+        return spaceGuid, nil
+    }
+
+    whisk.Debug(whisk.DbgError, "auth not found in properties: %#q\n", props)
+    errStr := wski18n.T("Auth key property value is not set")
+    werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+    return "", werr
+}
+
+func isBlockingTimeout(err error) (bool) {
+    var blockingTimeout bool
+
+    whiskErr, isWhiskErr := err.(*whisk.WskError)
+
+    if isWhiskErr && whiskErr.TimedOut {
+        blockingTimeout = true
+    }
+
+    return blockingTimeout
+}
+
+func isApplicationError(err error) (bool) {
+    var applicationError bool
+
+    whiskErr, isWhiskErr := err.(*whisk.WskError)
+
+    if isWhiskErr && whiskErr.ApplicationError {
+        applicationError = true
+    }
+
+    return applicationError
 }
diff --git a/commands/wsk.go b/commands/wsk.go
index c4b2712..beca322 100644
--- a/commands/wsk.go
+++ b/commands/wsk.go
@@ -1,31 +1,60 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package commands
 
-import "github.com/spf13/cobra"
+import (
+    "github.com/spf13/cobra"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
+)
 
 // WskCmd defines the entry point for the cli.
 var WskCmd = &cobra.Command{
-	Use:              "wsk",
-	Short:            "Whisk cloud computing command line interface.",
-	Long:             logoText(),
-	PersistentPreRun: parseConfigFlags,
+    Use:              "wsk",
+    Short:            wski18n.T("OpenWhisk cloud computing command line interface."),
+    Long:             logoText(),
+    SilenceUsage:     true,
+    PersistentPreRunE:parseConfigFlags,
 }
 
+
+
+
 func init() {
+    WskCmd.SetHelpTemplate(`{{with or .Long .Short }}{{.}}
+{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`)
 
-	WskCmd.AddCommand(
-		actionCmd,
-		activationCmd,
-		packageCmd,
-		ruleCmd,
-		triggerCmd,
-		sdkCmd,
-		propertyCmd,
-		namespaceCmd,
-		listCmd,
-	)
+    WskCmd.AddCommand(
+        actionCmd,
+        activationCmd,
+        packageCmd,
+        ruleCmd,
+        triggerCmd,
+        sdkCmd,
+        propertyCmd,
+        namespaceCmd,
+        listCmd,
+        apiExperimentalCmd,
+        apiCmd,
+    )
 
-	WskCmd.PersistentFlags().BoolVarP(&flags.global.verbose, "verbose", "v", false, "verbose output")
-	WskCmd.PersistentFlags().StringVarP(&flags.global.auth, "auth", "u", "", "authorization key")
-	WskCmd.PersistentFlags().StringVar(&flags.global.apihost, "apihost", "", "whisk API host")
-	WskCmd.PersistentFlags().StringVar(&flags.global.apiversion, "apiversion", "", "whisk API version")
+    WskCmd.PersistentFlags().BoolVarP(&flags.global.verbose, "verbose", "v", false, wski18n.T("verbose output"))
+    WskCmd.PersistentFlags().BoolVarP(&flags.global.debug, "debug", "d", false, wski18n.T("debug level output"))
+    WskCmd.PersistentFlags().StringVarP(&flags.global.auth, "auth", "u", "", wski18n.T("authorization `KEY`"))
+    WskCmd.PersistentFlags().StringVar(&flags.global.apihost, "apihost", "", wski18n.T("whisk API `HOST`"))
+    WskCmd.PersistentFlags().StringVar(&flags.global.apiversion, "apiversion", "", wski18n.T("whisk API `VERSION`"))
+    WskCmd.PersistentFlags().BoolVarP(&flags.global.insecure, "insecure", "i", false, wski18n.T("bypass certificate checking"))
 }
diff --git a/gradle/docker.gradle b/gradle/docker.gradle
new file mode 100644
index 0000000..f716c7b
--- /dev/null
+++ b/gradle/docker.gradle
@@ -0,0 +1,99 @@
+import groovy.time.*
+
+/**
+ * Utility to build docker images based in gradle projects
+ *
+ * This extends gradle's 'application' plugin logic with a 'distDocker' task which builds
+ * a docker image from the Dockerfile of the project that applies this file. The image
+ * is automatically tagged and pushed if a tag and/or a registry is given.
+ *
+ * Parameters that can be set on project level:
+ * - dockerImageName (required): The name of the image to build (e.g. controller)
+ * - dockerRegistry (optional): The registry to push to
+ * - dockerImageTag (optional, default 'latest'): The tag for the image
+ * - dockerImagePrefix (optional, default 'whisk'): The prefix for the image,
+ *       'controller' becomes 'whisk/controller' per default
+ * - dockerTimeout (optional, default 840): Timeout for docker operations in seconds
+ * - dockerRetries (optional, default 3): How many times to retry docker operations
+ * - dockerBinary (optional, default 'docker'): The binary to execute docker commands
+ * - dockerBuildArgs (options, default ''): Project specific custom docker build arguments
+ * - dockerHost (optional): The docker host to run commands on, default behaviour is
+ *       docker's own DOCKER_HOST environment variable
+ */
+
+ext {
+    dockerRegistry = project.hasProperty('dockerRegistry') ? dockerRegistry + '/' : ''
+    dockerImageTag = project.hasProperty('dockerImageTag') ? dockerImageTag : 'latest'
+    dockerImagePrefix = project.hasProperty('dockerImagePrefix') ? dockerImagePrefix : 'whisk'
+    dockerTimeout = project.hasProperty('dockerTimeout') ? dockerTimeout.toInteger() : 840
+    dockerRetries = project.hasProperty('dockerRetries') ? dockerRetries.toInteger() : 3
+    dockerBinary = project.hasProperty('dockerBinary') ? [dockerBinary] : ['docker']
+    dockerBuildArg = ['build']
+}
+ext.dockerTaggedImageName = dockerRegistry + dockerImagePrefix + '/' + dockerImageName + ':' + dockerImageTag
+
+if(project.hasProperty('dockerHost')) {
+    dockerBinary += ['--host', project.dockerHost]
+}
+
+if(project.hasProperty('dockerBuildArgs')) {
+    dockerBuildArgs.each { arg  ->
+        dockerBuildArg += ['--build-arg', arg]
+    }
+}
+
+task distDocker {
+    doLast {
+        def start = new Date()
+        def cmd = dockerBinary + dockerBuildArg + ['-t', dockerImageName, project.buildscript.sourceFile.getParentFile().getAbsolutePath()]
+        retry(cmd, dockerRetries, dockerTimeout)
+        println("Building '${dockerImageName}' took ${TimeCategory.minus(new Date(), start)}")
+    }
+}
+task tagImage {
+    doLast {
+        def versionString = (dockerBinary + ['-v']).execute().text
+        def matched = (versionString =~ /(\d+)\.(\d+)\.(\d+)/)
+
+        def major = matched[0][1] as int
+        def minor = matched[0][2] as int
+
+        def dockerCmd = ['tag']
+        if(major == 1 && minor < 12) {
+            dockerCmd += ['-f']
+        }
+        retry(dockerBinary + dockerCmd + [dockerImageName, dockerTaggedImageName], dockerRetries, dockerTimeout)
+    }
+}
+
+task pushImage {
+    doLast {
+        def cmd = dockerBinary + ['push', dockerTaggedImageName]
+        retry(cmd, dockerRetries, dockerTimeout)
+    }
+}
+pushImage.dependsOn tagImage
+pushImage.onlyIf { dockerRegistry != '' }
+distDocker.finalizedBy pushImage
+
+def retry(cmd, retries, timeout) {
+    println("${new Date()}: Executing '${cmd.join(" ")}'")
+    def proc = cmd.execute()
+    proc.consumeProcessOutput(System.out, System.err)
+    proc.waitForOrKill(timeout * 1000)
+    if(proc.exitValue() != 0) {
+        def message = "${new Date()}: Command '${cmd.join(" ")}' failed with exitCode ${proc.exitValue()}"
+        if(proc.exitValue() == 143) { // 143 means the process was killed (SIGTERM signal)
+            message = "${new Date()}: Command '${cmd.join(" ")}' was killed after ${timeout} seconds"
+        }
+
+        if(retries > 1) {
+            println("${message}, ${retries-1} retries left, retrying...")
+            retry(cmd, retries-1, timeout)
+        }
+        else {
+            println("${message}, no more retries left, aborting...")
+            throw new GradleException(message)
+        }
+    }
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..ca78035
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cd3a0f7
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 05 17:13:49 EDT 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..27309d9
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100755
index 0000000..f6d5974
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windows variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+if "%@eval[2+2]" == "4" goto 4NT_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+goto execute

+

+:4NT_args

+@rem Get arguments from the 4NT Shell from JP Software

+set CMD_LINE_ARGS=%$

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/main.go b/main.go
index 208db38..9ee44cb 100644
--- a/main.go
+++ b/main.go
@@ -1,21 +1,105 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package main
 
 import (
-	"fmt"
+    "fmt"
+    "os"
+    "reflect"
+    goi18n "github.com/nicksnyder/go-i18n/i18n"
+    "github.com/fatih/color"
 
-	"github.ibm.com/BlueMix-Fabric/go-whisk-cli/commands"
+    "github.com/openwhisk/openwhisk-client-go/whisk"
+    "github.com/openwhisk/openwhisk-cli/commands"
+    "github.com/openwhisk/openwhisk-cli/wski18n"
+    "github.com/mattn/go-colorable"
 )
 
-func main() {
-	defer func() {
-		if r := recover(); r != nil {
-			fmt.Println(r)
-			fmt.Println("Application exited unexpectedly")
-		}
-	}()
+// CLI_BUILD_TIME holds the time of the CLI build.  During gradle builds,
+// this value will be overwritten via the command:
+//     go build -ldflags "-X main.CLI_BUILD_TIME=nnnnn"   // nnnnn is the new timestamp
+var CLI_BUILD_TIME string = "not set"
 
-	if err := commands.Execute(); err != nil {
-		fmt.Println(err)
-		return
-	}
+var cliDebug = os.Getenv("WSK_CLI_DEBUG")  // Useful for tracing init() code
+
+var T goi18n.TranslateFunc
+
+func init() {
+    if len(cliDebug) > 0 {
+        whisk.SetDebug(true)
+    }
+
+    T = wski18n.T
+
+    // Rest of CLI uses the Properties struct, so set the build time there
+    commands.Properties.CLIVersion = CLI_BUILD_TIME
+}
+
+func main() {
+    var exitCode int = 0
+    var displayUsage bool = false
+    var displayMsg bool = false
+    var msgDisplayed bool = true
+    var displayPrefix bool = true
+
+    defer func() {
+        if r := recover(); r != nil {
+            fmt.Println(r)
+            fmt.Println(T("Application exited unexpectedly"))
+        }
+    }()
+
+    if err := commands.Execute(); err != nil {
+        whisk.Debug(whisk.DbgInfo, "err object type: %s\n", reflect.TypeOf(err).String())
+
+        werr, isWskError := err.(*whisk.WskError)  // Is the err a WskError?
+        if isWskError {
+            whisk.Debug(whisk.DbgError, "Got a *whisk.WskError error: %#v\n", werr)
+            displayUsage = werr.DisplayUsage
+            displayMsg = werr.DisplayMsg
+            msgDisplayed = werr.MsgDisplayed
+            displayPrefix = werr.DisplayPrefix
+            exitCode = werr.ExitCode
+        } else {
+            whisk.Debug(whisk.DbgError, "Got some other error: %s\n", err)
+            fmt.Fprintf(os.Stderr, "%s\n", err)
+
+            displayUsage = false   // Cobra already displayed the usage message
+            exitCode = 1;
+        }
+
+        outputStream := colorable.NewColorableStderr()
+
+        // If the err msg should be displayed to the console and it has not already been
+        // displayed, display it now.
+        if displayMsg && !msgDisplayed && displayPrefix && exitCode != 0 {
+            fmt.Fprintf(outputStream, "%s%s\n", color.RedString(T("error: ")), err)
+        } else if displayMsg && !msgDisplayed && !displayPrefix && exitCode != 0 {
+            fmt.Fprintf(outputStream, "%s\n", err)
+        } else if displayMsg && !msgDisplayed && exitCode == 0 {
+            fmt.Fprintf(outputStream, "%s\n", err)
+        }
+
+        // Displays usage
+        if displayUsage {
+            fmt.Fprintf(outputStream, T("Run '{{.Name}} --help' for usage.\n",
+                map[string]interface{}{ "Name" : commands.WskCmd.CommandPath()}))
+        }
+    }
+    os.Exit(exitCode)
+    return
 }
diff --git a/tests/src/dat/empty.js b/tests/src/dat/empty.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/src/dat/empty.js
diff --git a/tests/src/dat/hello.js b/tests/src/dat/hello.js
new file mode 100644
index 0000000..c40254d
--- /dev/null
+++ b/tests/src/dat/hello.js
@@ -0,0 +1,8 @@
+/**
+ * Hello, world.
+ */
+function main(params) {
+    greeting = 'hello, ' + params.payload + '!'
+    console.log(greeting);
+    return {payload: greeting}
+}
\ No newline at end of file
diff --git a/tests/src/dat/invalidInput1.json b/tests/src/dat/invalidInput1.json
new file mode 100644
index 0000000..da57a79
--- /dev/null
+++ b/tests/src/dat/invalidInput1.json
@@ -0,0 +1,3 @@
+{
+  "invalidJSON":
+}
diff --git a/tests/src/dat/invalidInput2.json b/tests/src/dat/invalidInput2.json
new file mode 100644
index 0000000..275fa9f
--- /dev/null
+++ b/tests/src/dat/invalidInput2.json
@@ -0,0 +1,4 @@
+{
+  "invalid": "JS
+  ON"
+}
diff --git a/tests/src/dat/invalidInput3.json b/tests/src/dat/invalidInput3.json
new file mode 100644
index 0000000..3272df5
--- /dev/null
+++ b/tests/src/dat/invalidInput3.json
@@ -0,0 +1,2 @@
+{
+  "invalid": "JSON"
diff --git a/tests/src/dat/invalidInput4.json b/tests/src/dat/invalidInput4.json
new file mode 100644
index 0000000..63c9ade
--- /dev/null
+++ b/tests/src/dat/invalidInput4.json
@@ -0,0 +1,3 @@
+{
+  "invalid": "JS"ON"
+}
\ No newline at end of file
diff --git a/tests/src/dat/malformed.js b/tests/src/dat/malformed.js
new file mode 100644
index 0000000..587be6b
--- /dev/null
+++ b/tests/src/dat/malformed.js
@@ -0,0 +1 @@
+x
diff --git a/tests/src/integration/command_test.go b/tests/src/integration/command_test.go
new file mode 100644
index 0000000..599cb7f
--- /dev/null
+++ b/tests/src/integration/command_test.go
@@ -0,0 +1,549 @@
+// +build native
+
+package tests
+
+import (
+	"testing"
+	"os"
+	"github.com/stretchr/testify/assert"
+	"github.com/openwhisk/openwhisk-cli/tests/src/integration/common"
+)
+
+var wsk *common.Wsk = common.NewWsk()
+var tmpProp = os.Getenv("GOPATH") + "/src/github.com/openwhisk/openwhisk-cli/wskprops.tmp"
+var invalidArgs []common.InvalidArg
+var invalidParamMsg = "Arguments for '-p' must be a key/value pair"
+var invalidAnnotMsg = "Arguments for '-a' must be a key/value pair"
+var invalidParamFileMsg = "An argument must be provided for '-P'"
+var invalidAnnotFileMsg = "An argument must be provided for '-A'"
+
+var emptyFile = common.GetTestActionFilename("emtpy.js")
+var helloFile = common.GetTestActionFilename("hello.js")
+var missingFile = "notafile"
+var emptyFileMsg = "File '" + emptyFile + "' is not a valid file or it does not exist"
+var missingFileMsg = "File '" + missingFile + "' is not a valid file or it does not exist"
+
+// Test case to check if the binary exits.
+func TestWskExist(t *testing.T) {
+	assert.True(t, wsk.Exists(), "The binary should exist.")
+}
+
+func TestHelpUsageInfoCommand(t *testing.T) {
+	stdout, err := wsk.RunCommand("-h")
+	assert.Equal(t, nil, err, "The command -h failed to run.")
+	assert.Contains(t, string(stdout), "Usage:", "The output of the command -h does not contain \"Usage\".")
+	assert.Contains(t, string(stdout), "Flags:", "The output of the command -h does not contain \"Flags\".")
+	assert.Contains(t, string(stdout), "Available Commands:",
+		"The output of the command -h does not contain \"Available Commands\".")
+	assert.Contains(t, string(stdout), "--help", "The output of the command -h does not contain \"--help\".")
+}
+
+func TestHelpUsageInfoCommandLanguage(t *testing.T) {
+	os.Setenv("LANG", "de_DE")
+	assert.Equal(t, "de_DE", os.Getenv("LANG"), "The environment variable LANG has not been set to de_DE.")
+	TestHelpUsageInfoCommand(t)
+}
+
+func TestShowCLIBuildVersion(t *testing.T) {
+	stdout, err := wsk.RunCommand("property", "get", "--cliversion")
+	assert.Equal(t, nil, err, "The command property get --cliversion failed to run.")
+	assert.Contains(t, string(stdout), "whisk CLI version",
+		"The output of the command property get --cliversion does not contain \"whisk CLI version\".")
+}
+
+func TestShowAPIVersion(t *testing.T) {
+	stdout, err := wsk.RunCommand("property", "get", "--apiversion")
+	assert.Equal(t, nil, err, "The command property get --apiversion failed to run.")
+	assert.Contains(t, string(stdout), "whisk API version",
+		"The output of the command property get --apiversion does not contain \"whisk API version\".")
+}
+
+// Test case to verify the default namespace _.
+func TestDefaultNamespace(t *testing.T) {
+	common.CreateFile(tmpProp)
+	common.WriteFile(tmpProp, []string{"NAMESPACE="})
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("property", "get", "-i", "--namespace")
+	assert.Equal(t, nil, err, "The command property get -i --namespace failed to run.")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk namespace _",
+		"The output of the command does not contain \"whisk namespace _\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to validate default property values.
+func TestValidateDefaultProperties(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("property", "unset", "--auth", "--apihost", "--apiversion", "--namespace")
+	assert.Equal(t, nil, err, "The command property unset failed to run.")
+	outputString := string(stdout)
+	assert.Contains(t, outputString, "ok: whisk auth unset",
+		"The output of the command does not contain \"ok: whisk auth unset\".")
+	assert.Contains(t, outputString, "ok: whisk API host unset",
+		"The output of the command does not contain \"ok: whisk API host unset\".")
+	assert.Contains(t, outputString, "ok: whisk API version unset",
+		"The output of the command does not contain \"ok: whisk API version unset\".")
+	assert.Contains(t, outputString, "ok: whisk namespace unset",
+		"The output of the command does not contain \"ok: whisk namespace unset\".")
+
+	stdout, err = wsk.RunCommand("property", "get", "--auth")
+	assert.Equal(t, nil, err, "The command property get --auth failed to run.")
+	assert.Equal(t, common.RemoveRedundentSpaces(string(stdout)), "whisk auth",
+		"The output of the command does not equal to \"whisk auth\".")
+
+	stdout, err = wsk.RunCommand("property", "get", "--apihost")
+	assert.Equal(t, nil, err, "The command property get --apihost failed to run.")
+	assert.Equal(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API host",
+		"The output of the command does not equal to \"whisk API host\".")
+
+	stdout, err = wsk.RunCommand("property", "get", "--namespace")
+	assert.Equal(t, nil, err, "The command property get --namespace failed to run.")
+	assert.Equal(t, common.RemoveRedundentSpaces(string(stdout)), "whisk namespace _",
+		"The output of the command does not equal to \"whisk namespace _\".")
+
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to set auth in property file.
+func TestSetAuth(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	_, err := wsk.RunCommand("property", "set", "--auth", "testKey")
+	assert.Equal(t, nil, err, "The command property set --auth testKey failed to run.")
+	output := common.ReadFile(tmpProp)
+	assert.Contains(t, output, "AUTH=testKey",
+		"The wsk property file does not contain \"AUTH=testKey\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to set multiple property values with single command.
+func TestSetMultipleValues(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	_, err := wsk.RunCommand("property", "set", "--auth", "testKey", "--apihost", "openwhisk.ng.bluemix.net",
+		"--apiversion", "v1")
+	assert.Equal(t, nil, err, "The command property set --auth --apihost --apiversion failed to run.")
+	output := common.ReadFile(tmpProp)
+	assert.Contains(t, output, "AUTH=testKey", "The wsk property file does not contain \"AUTH=testKey\".")
+	assert.Contains(t, output, "APIHOST=openwhisk.ng.bluemix.net",
+		"The wsk property file does not contain \"APIHOST=openwhisk.ng.bluemix.net\".")
+	assert.Contains(t, output, "APIVERSION=v1", "The wsk property file does not contain \"APIVERSION=v1\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to reject bad command.
+func TestRejectBadComm(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("bogus")
+	assert.NotEqual(t, nil, err, "The command bogus should fail to run.")
+	assert.Contains(t, string(stdout), "Run 'wsk --help' for usage",
+		"The output of the command does not contain \"Run 'wsk --help' for usage\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to reject a command when the API host is not set.
+func TestRejectCommAPIHostNotSet(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("property", "get")
+	assert.NotEqual(t, nil, err, "The command property get --apihost --apiversion should fail to run.")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)),
+		"The API host is not valid: An API host must be provided",
+		"The output of the command does not contain \"The API host is not valid: An API host must be provided\".")
+	common.DeleteFile(tmpProp)
+}
+
+func initInvalidArgsNotEnoughParamsArgs() {
+	invalidArgs = []common.InvalidArg{
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-p"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-p", "key"},
+			Err: invalidParamMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-P"},
+			Err: invalidParamFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-a"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-a", "key"},
+			Err: invalidAnnotMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-A"},
+			Err: invalidAnnotFileMsg,
+		},
+	}
+}
+
+func initInvalidArgsMissingInvalidParamsAnno(){
+	invalidArgs = []common.InvalidArg{
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", helloFile, "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", helloFile, "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-P", emptyFile},
+			Err: emptyFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", helloFile, "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", helloFile, "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName", "-A", missingFile},
+			Err: missingFileMsg,
+		},
+	}
+}
+
+// Test case to reject commands that are executed with not enough param or annotation arguments.
+func TestRejectCommandsNotEnoughParamsArgs(t *testing.T) {
+	initInvalidArgsNotEnoughParamsArgs()
+	for _, invalidArg := range invalidArgs {
+		stdout, err := wsk.RunCommand(invalidArg.Cmd...)
+		outputString := string(stdout)
+		assert.NotEqual(t, nil, err, "The command should fail to run.")
+		assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+		assert.Contains(t, outputString, invalidArg.Err,
+			"The output of the command does not contain " + invalidArg.Err)
+		assert.Contains(t, outputString, "Run 'wsk --help' for usage",
+			"The output of the command does not contain \"Run 'wsk --help' for usage\".")
+	}
+}
+
+// Test case to reject commands that are executed with a missing or invalid parameter or annotation file.
+func TestRejectCommandsMissingIvalidParamsAnno(t *testing.T) {
+	initInvalidArgsMissingInvalidParamsAnno()
+	for _, invalidArg := range invalidArgs {
+		stdout, err := wsk.RunCommand(invalidArg.Cmd...)
+		outputString := string(stdout)
+		assert.NotEqual(t, nil, err, "The command should fail to run.")
+		assert.Equal(t, "exit status 2", err.Error(), "The error should be exit status 1.")
+		assert.Contains(t, outputString, invalidArg.Err,
+			"The output of the command does not contain " + invalidArg.Err)
+		assert.Contains(t, outputString, "Run 'wsk --help' for usage",
+			"The output of the command does not contain \"Run 'wsk --help' for usage\".")
+	}
+}
diff --git a/tests/src/integration/common/utils.go b/tests/src/integration/common/utils.go
new file mode 100644
index 0000000..1830490
--- /dev/null
+++ b/tests/src/integration/common/utils.go
@@ -0,0 +1,79 @@
+package common
+
+import (
+	"fmt"
+	"os"
+	"regexp"
+	"io"
+)
+
+func checkError(err error) {
+	if err != nil {
+		fmt.Println(err.Error())
+		os.Exit(0)
+	}
+}
+
+func CreateFile(filePath string) {
+	var _, err = os.Stat(filePath)
+
+	if os.IsNotExist(err) {
+		var file, err = os.Create(filePath)
+		checkError(err)
+		defer file.Close()
+	}
+	return
+}
+
+func ReadFile(filePath string) string {
+	var file, err = os.OpenFile(filePath, os.O_RDWR, 0644)
+	checkError(err)
+	defer file.Close()
+
+	var text = make([]byte, 1024)
+	for {
+		n, err := file.Read(text)
+		if err != io.EOF {
+			checkError(err)
+		}
+		if n == 0 {
+			break
+		}
+	}
+	return string(text)
+}
+
+func WriteFile(filePath string, lines []string) {
+	var file, err = os.OpenFile(filePath, os.O_RDWR, 0644)
+	checkError(err)
+	defer file.Close()
+
+	for _, each := range lines {
+		_, err = file.WriteString(each + "\n")
+		checkError(err)
+	}
+
+	err = file.Sync()
+	checkError(err)
+}
+
+func DeleteFile(filePath string) {
+	var err = os.Remove(filePath)
+	checkError(err)
+}
+
+func RemoveRedundentSpaces(str string) string {
+	re_leadclose_whtsp := regexp.MustCompile(`^[\s\p{Zs}]+|[\s\p{Zs}]+$`)
+	re_inside_whtsp := regexp.MustCompile(`[\s\p{Zs}]{2,}`)
+	final := re_leadclose_whtsp.ReplaceAllString(str, "")
+	return re_inside_whtsp.ReplaceAllString(final, " ")
+}
+
+func GetTestActionFilename(fileName string) string {
+	return os.Getenv("GOPATH") + "/src/github.com/openwhisk/openwhisk-cli/tests/src/dat/" + fileName
+}
+
+type InvalidArg struct {
+	Cmd []string
+	Err string
+}
\ No newline at end of file
diff --git a/tests/src/integration/common/wsk.go b/tests/src/integration/common/wsk.go
new file mode 100644
index 0000000..78716c9
--- /dev/null
+++ b/tests/src/integration/common/wsk.go
@@ -0,0 +1,51 @@
+package common
+
+import (
+	"os"
+	"os/exec"
+)
+
+const cmd = "wsk"
+const arg = "-i"
+
+type Wsk struct {
+	Path string
+	Arg []string
+	Dir string
+	Wskprops *Wskprops
+}
+
+func NewWsk() *Wsk {
+	return NewWskWithPath(os.Getenv("GOPATH") + "/src/github.com/openwhisk/openwhisk-cli/")
+}
+
+func NewWskWithPath(path string) *Wsk {
+	var dep Wsk
+	dep.Path = cmd
+	dep.Arg = []string{arg}
+	dep.Dir = path
+	dep.Wskprops = GetWskprops()
+	return &dep
+}
+
+func (wsk *Wsk)Exists() bool {
+	_, err := os.Stat(wsk.Dir + wsk.Path);
+	if err == nil {
+		return true
+	} else {
+		return false
+	}
+}
+
+func (wsk *Wsk)RunCommand(s ...string) ([]byte, error) {
+	cs := wsk.Arg
+	cs = append(cs, s...)
+	command := exec.Command(wsk.Path, cs...)
+	command.Dir = wsk.Dir
+	return command.CombinedOutput()
+}
+
+func (wsk *Wsk)ListNamespaces() ([]byte, error) {
+	return wsk.RunCommand("namespace", "list", "--apihost", wsk.Wskprops.APIHost,
+		"--auth", wsk.Wskprops.AuthKey)
+}
\ No newline at end of file
diff --git a/tests/src/integration/common/wskprops.go b/tests/src/integration/common/wskprops.go
new file mode 100644
index 0000000..ae493c1
--- /dev/null
+++ b/tests/src/integration/common/wskprops.go
@@ -0,0 +1,39 @@
+package common
+
+import (
+	"github.com/spf13/viper"
+	"io/ioutil"
+	"os"
+)
+
+type Wskprops struct {
+	APIHost string
+	APIVersion string
+	AuthKey string
+	ControllerHost string
+	ControllerPort string
+}
+
+func GetWskprops() *Wskprops {
+	var dep Wskprops
+	dep.APIHost = ""
+	dep.AuthKey = ""
+	dep.APIVersion = "v1"
+
+	viper.SetConfigName("whisk")
+	viper.AddConfigPath(os.Getenv("OPENWHISK_HOME"))
+
+	err := viper.ReadInConfig()
+	if err == nil {
+		authPath := viper.GetString("testing.auth")
+
+		b, err := ioutil.ReadFile(authPath)
+		if err == nil {
+			dep.AuthKey = string(b)
+		}
+		dep.APIHost = viper.GetString("router.host")
+		dep.ControllerHost = viper.GetString("router.host")
+		dep.ControllerPort = viper.GetString("controller.host.port")
+	}
+	return &dep
+}
diff --git a/tests/src/integration/integration_test.go b/tests/src/integration/integration_test.go
new file mode 100644
index 0000000..d46e108
--- /dev/null
+++ b/tests/src/integration/integration_test.go
@@ -0,0 +1,597 @@
+// +build integration
+
+package tests
+
+import (
+	"testing"
+	"github.com/stretchr/testify/assert"
+	"github.com/openwhisk/openwhisk-cli/tests/src/integration/common"
+	"os"
+	"strings"
+)
+
+var invalidArgs []common.InvalidArg
+var invalidArgsMsg = "error: Invalid argument(s)"
+var tooFewArgsMsg = invalidArgsMsg + "."
+var tooManyArgsMsg = invalidArgsMsg + ": "
+var actionNameActionReqMsg = "An action name and action are required."
+var actionNameReqMsg = "An action name is required."
+var actionOptMsg = "An action is optional."
+var packageNameReqMsg = "A package name is required."
+var packageNameBindingReqMsg = "A package name and binding name are required."
+var ruleNameReqMsg = "A rule name is required."
+var ruleTriggerActionReqMsg = "A rule, trigger and action name are required."
+var activationIdReq = "An activation ID is required."
+var triggerNameReqMsg = "A trigger name is required."
+var optNamespaceMsg = "An optional namespace is the only valid argument."
+var optPayloadMsg = "A payload is optional."
+var noArgsReqMsg = "No arguments are required."
+var invalidArg = "invalidArg"
+var apiCreateReqMsg = "Specify a swagger file or specify an API base path with an API path, an API verb, and an action name."
+var apiGetReqMsg = "An API base path or API name is required."
+var apiDeleteReqMsg = "An API base path or API name is required.  An optional API relative path and operation may also be provided."
+var apiListReqMsg = "Optional parameters are: API base path (or API name), API relative path and operation."
+var invalidShared = "Cannot use value '" + invalidArg + "' for shared"
+
+func initInvalidArgs() {
+	invalidArgs = []common.InvalidArg{
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "create"},
+			Err: tooFewArgsMsg + " " + apiCreateReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "create", "/basepath", "/path", "GET", "action", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + apiCreateReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "get"},
+			Err: tooFewArgsMsg + " " + apiGetReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "get", "/basepath", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + apiGetReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "delete"},
+			Err: tooFewArgsMsg + " " + apiDeleteReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "delete", "/basepath", "/path", "GET", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + apiDeleteReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"api-experimental", "list", "/basepath", "/path", "GET", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + apiListReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "create"},
+			Err: tooFewArgsMsg + " " + actionNameActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "create", "someAction"},
+			Err: tooFewArgsMsg + " " + actionNameActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "create", "actionName", "artifactName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "update"},
+			Err: tooFewArgsMsg + " " + actionNameReqMsg + " " + actionOptMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "update", "actionName", "artifactName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + actionNameReqMsg + " " + actionOptMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "delete"},
+			Err: tooFewArgsMsg + " " + actionNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "delete", "actionName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "get"},
+			Err: tooFewArgsMsg + " " + actionNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "get", "actionName", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "list", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "invoke"},
+			Err: tooFewArgsMsg + " " + actionNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"action", "invoke", "actionName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "list", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "get"},
+			Err: tooFewArgsMsg + " " + activationIdReq,
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "get", "activationID", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "logs"},
+			Err: tooFewArgsMsg + " " + activationIdReq,
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "logs", "activationID", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+
+		common.InvalidArg {
+			Cmd: []string{"activation", "result"},
+			Err: tooFewArgsMsg + " " + activationIdReq,
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "result", "activationID", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"activation", "poll", "activationID", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"namespace", "list", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + noArgsReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"namespace", "get", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "create"},
+			Err: tooFewArgsMsg + " " + packageNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "create", "packageName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "create", "packageName", "--shared", invalidArg},
+			Err: invalidShared,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "update"},
+			Err: tooFewArgsMsg + " " + packageNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "update", "packageName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "update", "packageName", "--shared", invalidArg},
+			Err: invalidShared,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "get"},
+			Err: tooFewArgsMsg + " " +packageNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "get", "packageName", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "bind"},
+			Err: tooFewArgsMsg + " " + packageNameBindingReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "bind", "packageName"},
+			Err: tooFewArgsMsg + " " +packageNameBindingReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "bind", "packageName", "bindingName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "list", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "delete"},
+			Err: tooFewArgsMsg + " " + packageNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "delete", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"package", "refresh", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "enable"},
+			Err: tooFewArgsMsg + " " + ruleNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "enable", "ruleName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "disable"},
+			Err: tooFewArgsMsg + " " + ruleNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "disable", "ruleName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "status"},
+			Err: tooFewArgsMsg + " " + ruleNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "status", "ruleName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "create"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "create", "ruleName"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "create", "ruleName", "triggerName"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "create", "ruleName", "triggerName", "actionName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+
+		common.InvalidArg {
+			Cmd: []string{"rule", "update"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "update", "ruleName"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "update", "ruleName", "triggerName"},
+			Err: tooFewArgsMsg + " " + ruleTriggerActionReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "update", "ruleName", "triggerName", "actionName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "get"},
+			Err: tooFewArgsMsg + " " + ruleNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "get", "ruleName", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "delete"},
+			Err: tooFewArgsMsg + " " + ruleNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "delete", "ruleName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"rule", "list", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+
+		common.InvalidArg {
+			Cmd: []string{"trigger", "fire"},
+			Err: tooFewArgsMsg + " " + triggerNameReqMsg + " " + optPayloadMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "fire", "triggerName", "triggerPayload", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + triggerNameReqMsg + " " +optPayloadMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "create"},
+			Err: tooFewArgsMsg + " " + triggerNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "create", "triggerName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "update"},
+			Err: tooFewArgsMsg + " " + triggerNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "update", "triggerName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+
+		common.InvalidArg {
+			Cmd: []string{"trigger", "get"},
+			Err: tooFewArgsMsg + " " + triggerNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "get", "triggerName", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "delete"},
+			Err: tooFewArgsMsg + " " + triggerNameReqMsg,
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "delete", "triggerName", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ".",
+		},
+		common.InvalidArg {
+			Cmd: []string{"trigger", "list", "namespace", invalidArg},
+			Err: tooManyArgsMsg + invalidArg + ". " + optNamespaceMsg,
+		},
+	}
+}
+
+var wsk *common.Wsk = common.NewWsk()
+var tmpProp = os.Getenv("GOPATH") + "/src/github.com/openwhisk/openwhisk-cli/wskprops.tmp"
+
+// Test case to set apihost, auth, and namespace.
+func TestSetAPIHostAuthNamespace(t *testing.T) {
+	common.CreateFile(tmpProp)
+	common.WriteFile(tmpProp, []string{})
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	namespace, _ := wsk.ListNamespaces()
+	namespaces := strings.Split(strings.TrimSpace(string(namespace)), "\n")
+	expectedNamespace := string(namespaces[len(namespaces) - 1])
+	if (wsk.Wskprops.APIHost != "" && wsk.Wskprops.APIHost != "") {
+		stdout, err := wsk.RunCommand("property", "set", "--apihost", wsk.Wskprops.APIHost,
+			"--auth", wsk.Wskprops.AuthKey, "--namespace", expectedNamespace)
+		ouputString := string(stdout)
+		assert.Equal(t, nil, err, "The command property set --apihost --auth --namespace failed to run.")
+		assert.Contains(t, ouputString, "ok: whisk auth set to " + wsk.Wskprops.AuthKey,
+			"The output of the command property set --apihost --auth --namespace does not contain \"whisk auth key setting\".")
+		assert.Contains(t, ouputString, "ok: whisk API host set to " + wsk.Wskprops.APIHost,
+			"The output of the command property set --apihost --auth --namespace does not contain \"whisk API host setting\".")
+		assert.Contains(t, ouputString, "ok: whisk namespace set to " + expectedNamespace,
+			"The output of the command property set --apihost --auth --namespace does not contain \"whisk namespace setting\".")
+	}
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to show api build version using property file.
+func TestShowAPIBuildVersion(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("property", "set", "--apihost", wsk.Wskprops.APIHost,
+		"--apiversion", wsk.Wskprops.APIVersion)
+	assert.Equal(t, nil, err, "The command property set --apihost --apiversion failed to run.")
+	stdout, err = wsk.RunCommand("property", "get", "-i", "--apibuild")
+	assert.Equal(t, nil, err, "The command property get -i --apibuild failed to run.")
+	assert.NotContains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API build Unknown",
+		"The output of the command property get --apibuild does not contain \"whisk API build Unknown\".")
+	assert.NotContains(t, common.RemoveRedundentSpaces(string(stdout)), "Unable to obtain API build information",
+		"The output of the command property get --apibuild does not contain \"Unable to obtain API build information\".")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API build 20",
+		"The output of the command property get --apibuild does not contain \"whisk API build 20\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to fail to show api build when setting apihost to bogus value.
+func TestFailShowAPIBuildVersion(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	_, err := wsk.RunCommand("property", "set", "--apihost", "xxxx.yyyy")
+	assert.Equal(t, nil, err, "The command property set --apihost failed to run.")
+	stdout, err := wsk.RunCommand("property", "get", "-i", "--apibuild")
+	assert.NotEqual(t, nil, err, "The command property get -i --apibuild does not raise any error.")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API build Unknown",
+		"The output of the command property get --apibuild does not contain \"whisk API build Unknown\".")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "Unable to obtain API build information",
+		"The output of the command property get --apibuild does not contain \"Unable to obtain API build information\".")
+}
+
+// Test case to show api build using http apihost.
+func TestShowAPIBuildVersionHTTP(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	apihost := "http://" + wsk.Wskprops.ControllerHost + ":" + wsk.Wskprops.ControllerPort
+	stdout, err := wsk.RunCommand("property", "set", "--apihost", apihost)
+	assert.Equal(t, nil, err, "The command property set --apihost failed to run.")
+	stdout, err = wsk.RunCommand("property", "get", "-i", "--apibuild")
+	assert.Equal(t, nil, err, "The command property get -i --apibuild failed to run.")
+	assert.NotContains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API build Unknown",
+		"The output of the command property get --apibuild does not contain \"whisk API build Unknown\".")
+	assert.NotContains(t, common.RemoveRedundentSpaces(string(stdout)), "Unable to obtain API build information",
+		"The output of the command property get --apibuild does not contain \"Unable to obtain API build information\".")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "whisk API build 20",
+		"The output of the command property get --apibuild does not contain \"whisk API build 20\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to reject bad command.
+func TestRejectAuthCommNoKey(t *testing.T) {
+	common.CreateFile(tmpProp)
+
+	os.Setenv("WSK_CONFIG_FILE", tmpProp)
+	assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
+
+	stdout, err := wsk.RunCommand("list", "--apihost", wsk.Wskprops.APIHost,
+		"--apiversion", wsk.Wskprops.APIVersion)
+	assert.NotEqual(t, nil, err, "The command list should fail to run.")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "usage.",
+		"The output of the command does not contain \"usage.\".")
+	assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "--auth is required",
+		"The output of the command does not contain \"--auth is required\".")
+	common.DeleteFile(tmpProp)
+}
+
+// Test case to reject commands that are executed with invalid arguments.
+func TestRejectCommInvalidArgs(t *testing.T) {
+	initInvalidArgs()
+	for _, invalidArg := range invalidArgs {
+		cs := invalidArg.Cmd
+		cs = append(cs, "--apihost", wsk.Wskprops.APIHost)
+		stdout, err := wsk.RunCommand(cs...)
+		outputString := string(stdout)
+		assert.NotEqual(t, nil, err, "The command should fail to run.")
+		assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+		assert.Contains(t, outputString, invalidArg.Err,
+			"The output of the command does not contain " + invalidArg.Err)
+		assert.Contains(t, outputString, "Run 'wsk --help' for usage",
+			"The output of the command does not contain \"Run 'wsk --help' for usage\".")
+	}
+}
+
+// Test case to reject commands that are executed with invalid JSON for annotations and parameters.
+func TestRejectCommInvalidJSON(t *testing.T) {
+	helloFile := common.GetTestActionFilename("hello.js")
+	var invalidJSONInputs = []string{
+		"{\"invalid1\": }",
+		"{\"invalid2\": bogus}",
+		"{\"invalid1\": \"aKey\"",
+		"invalid \"string\"",
+		"{\"invalid1\": [1, 2, \"invalid\"\"arr\"]}",
+	}
+	var invalidJSONFiles = []string{
+		common.GetTestActionFilename("malformed.js"),
+		common.GetTestActionFilename("invalidInput1.json"),
+		common.GetTestActionFilename("invalidInput2.json"),
+		common.GetTestActionFilename("invalidInput3.json"),
+		common.GetTestActionFilename("invalidInput4.json"),
+	}
+	var invalidParamArg = "Invalid parameter argument"
+	var invalidAnnoArg = "Invalid annotation argument"
+	var paramCmds = []common.InvalidArg{
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", helloFile},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", helloFile},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "invoke", "actionName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName"},
+			Err: invalidParamArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "fire", "triggerName"},
+			Err: invalidParamArg,
+		},
+	}
+
+	var annotCmds = []common.InvalidArg{
+		common.InvalidArg{
+			Cmd: []string{"action", "create", "actionName", helloFile},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"action", "update", "actionName", helloFile},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "create", "packageName"},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "update", "packageName"},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"package", "bind", "packageName", "boundPackageName"},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "create", "triggerName"},
+			Err: invalidAnnoArg,
+		},
+		common.InvalidArg{
+			Cmd: []string{"trigger", "update", "triggerName"},
+			Err: invalidAnnoArg,
+		},
+	}
+
+	for _, cmd := range paramCmds {
+		for _, invalid := range invalidJSONInputs {
+			cs := cmd.Cmd
+			cs = append(cs, "-p", "key", invalid, "--apihost", wsk.Wskprops.APIHost)
+			stdout, err := wsk.RunCommand(cs...)
+			outputString := string(stdout)
+			assert.NotEqual(t, nil, err, "The command should fail to run.")
+			assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+			assert.Contains(t, outputString, cmd.Err,
+				"The output of the command does not contain " + cmd.Err + " .")
+		}
+		for _, invalid := range invalidJSONFiles {
+			cs := cmd.Cmd
+			cs = append(cs, "-P", invalid, "--apihost", wsk.Wskprops.APIHost)
+			stdout, err := wsk.RunCommand(cs...)
+			outputString := string(stdout)
+			assert.NotEqual(t, nil, err, "The command should fail to run.")
+			assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+			assert.Contains(t, outputString, cmd.Err,
+				"The output of the command does not contain " + cmd.Err + " .")
+		}
+	}
+
+	for _, cmd := range annotCmds {
+		for _, invalid := range invalidJSONInputs {
+			cs := cmd.Cmd
+			cs = append(cs, "-a", "key", invalid, "--apihost", wsk.Wskprops.APIHost)
+			stdout, err := wsk.RunCommand(cs...)
+			outputString := string(stdout)
+			assert.NotEqual(t, nil, err, "The command should fail to run.")
+			assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+			assert.Contains(t, outputString, cmd.Err,
+				"The output of the command does not contain " + cmd.Err + " .")
+		}
+		for _, invalid := range invalidJSONFiles {
+			cs := cmd.Cmd
+			cs = append(cs, "-A", invalid, "--apihost", wsk.Wskprops.APIHost)
+			stdout, err := wsk.RunCommand(cs...)
+			outputString := string(stdout)
+			assert.NotEqual(t, nil, err, "The command should fail to run.")
+			assert.Equal(t, "exit status 1", err.Error(), "The error should be exit status 1.")
+			assert.Contains(t, outputString, cmd.Err,
+				"The output of the command does not contain " + cmd.Err + " .")
+		}
+	}
+}
\ No newline at end of file
diff --git a/tools/travis/build_tag_releases.sh b/tools/travis/build_tag_releases.sh
new file mode 100755
index 0000000..71298f0
--- /dev/null
+++ b/tools/travis/build_tag_releases.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+declare -a os_list=()
+declare -a arc_list=("amd64" "386")
+build_file_name=${1:-"wsk"}
+zip_file_name=${2:-"OpenWhisk_CLI"}
+os=$TRAVIS_OS_NAME
+
+if [[ $TRAVIS_OS_NAME == 'linux' ]]; then
+    # Currently we have not set up the CI designated to build windows binaries, so we tentatively
+    # add the windows build into the linux CI environment.
+    os_list=("linux" "windows")
+elif [[ $TRAVIS_OS_NAME == 'osx' ]]; then
+    os_list=("darwin")
+fi
+
+for os in "${os_list[@]}"
+do
+    for arc in "${arc_list[@]}"
+    do
+        wsk=$build_file_name
+        os_name=$os
+        if [ "$os" == "windows" ]; then
+            wsk="$wsk.exe"
+        fi
+        if [ "$os" == "darwin" ]; then
+            os_name="mac"
+        fi
+        cd $TRAVIS_BUILD_DIR
+        GOOS=$os GOARCH=$arc go build -o build/$os/$arc/$wsk
+        cd build/$os/$arc
+        zip -r "$TRAVIS_BUILD_DIR/$zip_file_name-$TRAVIS_TAG-$os_name-$arc.zip" $wsk
+    done
+done
diff --git a/tools/travis/install_openwhisk.sh b/tools/travis/install_openwhisk.sh
new file mode 100755
index 0000000..ae0d5ed
--- /dev/null
+++ b/tools/travis/install_openwhisk.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+HOMEDIR="$(dirname "$TRAVIS_BUILD_DIR")"
+cd $HOMEDIR
+
+sudo gpasswd -a travis docker
+sudo -E bash -c 'echo '\''DOCKER_OPTS="-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock --api-enable-cors --storage-driver=aufs"'\'' > /etc/default/docker'
+
+# Docker
+sudo apt-get -y update -qq
+sudo apt-get -o Dpkg::Options::="--force-confold" --force-yes -y install docker-engine=1.12.0-0~trusty
+sudo service docker restart
+echo "Docker Version:"
+docker version
+echo "Docker Info:"
+docker info
+
+# Ansible
+pip install --user ansible==2.3.0.0
+
+# Clone the OpenWhisk code
+git clone --depth 3 https://github.com/openwhisk/openwhisk.git
+
+# Build script for Travis-CI.
+WHISKDIR="$HOMEDIR/openwhisk"
+
+ANSIBLE_CMD="ansible-playbook -i environments/local"
+
+cd $WHISKDIR/ansible
+$ANSIBLE_CMD setup.yml
+$ANSIBLE_CMD prereq.yml
+$ANSIBLE_CMD couchdb.yml
+$ANSIBLE_CMD initdb.yml
+
+cd $WHISKDIR
+./gradlew distDocker
+
+cd $WHISKDIR/ansible
+$ANSIBLE_CMD wipe.yml
+$ANSIBLE_CMD openwhisk.yml
diff --git a/wsk b/wsk
deleted file mode 100755
index 47cde91..0000000
--- a/wsk
+++ /dev/null
Binary files differ
diff --git a/wski18n/detection.go b/wski18n/detection.go
new file mode 100644
index 0000000..03d9be8
--- /dev/null
+++ b/wski18n/detection.go
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package wski18n
+
+import "github.com/cloudfoundry/jibber_jabber"
+
+type Detector interface {
+    DetectLocale() string
+    DetectLanguage() string
+}
+
+type JibberJabberDetector struct{}
+
+func (d *JibberJabberDetector) DetectLocale() string {
+    userLocale, err := jibber_jabber.DetectIETF()
+    if err != nil {
+        userLocale = ""
+    }
+    return userLocale
+}
+
+func (d *JibberJabberDetector) DetectLanguage() string {
+    lang, err := jibber_jabber.DetectLanguage()
+    if err != nil {
+        lang = ""
+    }
+    return lang
+}
diff --git a/wski18n/i18n.go b/wski18n/i18n.go
new file mode 100644
index 0000000..3c68b5f
--- /dev/null
+++ b/wski18n/i18n.go
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2015-2016 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package wski18n
+
+import (
+    "path/filepath"
+    "strings"
+
+    goi18n "github.com/nicksnyder/go-i18n/i18n"
+)
+
+const (
+    DEFAULT_LOCALE = "en_US"
+)
+
+var SUPPORTED_LOCALES = []string{
+    "de_DE",
+    "en_US",
+    "es_ES",
+    "fr_FR",
+    "it_IT",
+    "ja_JA",
+    "ko_KR",
+    "pt_BR",
+    "zh_Hans",
+    "zh_Hant",
+}
+
+var resourcePath = filepath.Join("wski18n", "resources")
+
+func GetResourcePath() string {
+    return resourcePath
+}
+
+func SetResourcePath(path string) {
+    resourcePath = path
+}
+
+var T goi18n.TranslateFunc
+var curLocale string
+
+func init() {
+    curLocale = Init(new(JibberJabberDetector))
+}
+
+func CurLocale() string {
+    return curLocale
+}
+
+func Locale(detector Detector) string {
+
+    // Use default locale until strings are translated
+    /*sysLocale := normalize(detector.DetectLocale())
+    if isSupported(sysLocale) {
+        return sysLocale
+    }
+
+    locale := defaultLocaleForLang(detector.DetectLanguage())
+    if locale != "" {
+        return locale
+    }*/
+
+    return DEFAULT_LOCALE
+}
+
+func Init(detector Detector) string {
+    l := Locale(detector)
+    InitWithLocale(l)
+    return l
+}
+
+func InitWithLocale(locale string) {
+    err := loadFromAsset(locale)
+    if err != nil {
+        panic(err)
+    }
+    T = goi18n.MustTfunc(locale)
+}
+
+func loadFromAsset(locale string) (err error) {
+    assetName := locale + ".all.json"
+    assetKey := filepath.Join(resourcePath, assetName)
+    bytes, err := Asset(assetKey)
+    if err != nil {
+        return
+    }
+    err = goi18n.ParseTranslationFileBytes(assetName, bytes)
+    return
+}
+
+func normalize(locale string) string {
+    locale = strings.ToLower(strings.Replace(locale, "-", "_", 1))
+    for _, l := range SUPPORTED_LOCALES {
+        if strings.EqualFold(locale, l) {
+            return l
+        }
+    }
+    switch locale {
+    case "zh_cn", "zh_sg":
+        return "zh_Hans"
+    case "zh_hk", "zh_tw":
+        return "zh_Hant"
+    }
+    return locale
+}
+
+func isSupported(locale string) bool {
+    for _, l := range SUPPORTED_LOCALES {
+        if strings.EqualFold(locale, l) {
+            return true
+        }
+    }
+    return false
+}
+
+func defaultLocaleForLang(lang string) string {
+    if lang != "" {
+        lang = strings.ToLower(lang)
+        for _, l := range SUPPORTED_LOCALES {
+            if lang == LangOfLocale(l) {
+                return l
+            }
+        }
+    }
+    return ""
+}
+
+func LangOfLocale(locale string) string {
+    if len(locale) < 2 {
+        return ""
+    }
+    return locale[0:2]
+}
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
new file mode 100644
index 0000000..723b874
--- /dev/null
+++ b/wski18n/i18n_resources.go
@@ -0,0 +1,469 @@
+// Code generated by go-bindata.
+// sources:
+// wski18n/resources/.DS_Store
+// wski18n/resources/de_DE.all.json
+// wski18n/resources/en_US.all.json
+// wski18n/resources/es_ES.all.json
+// wski18n/resources/fr_FR.all.json
+// wski18n/resources/it_IT.all.json
+// wski18n/resources/ja_JA.all.json
+// wski18n/resources/ko_KR.all.json
+// wski18n/resources/pt_BR.all.json
+// wski18n/resources/zh_Hans.all.json
+// wski18n/resources/zh_Hant.all.json
+// DO NOT EDIT!
+
+package wski18n
+
+import (
+	"bytes"
+	"compress/gzip"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+func bindataRead(data []byte, name string) ([]byte, error) {
+	gz, err := gzip.NewReader(bytes.NewBuffer(data))
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, gz)
+	clErr := gz.Close()
+
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+	if clErr != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
+type asset struct {
+	bytes []byte
+	info  os.FileInfo
+}
+
+type bindataFileInfo struct {
+	name    string
+	size    int64
+	mode    os.FileMode
+	modTime time.Time
+}
+
+func (fi bindataFileInfo) Name() string {
+	return fi.name
+}
+func (fi bindataFileInfo) Size() int64 {
+	return fi.size
+}
+func (fi bindataFileInfo) Mode() os.FileMode {
+	return fi.mode
+}
+func (fi bindataFileInfo) ModTime() time.Time {
+	return fi.modTime
+}
+func (fi bindataFileInfo) IsDir() bool {
+	return false
+}
+func (fi bindataFileInfo) Sys() interface{} {
+	return nil
+}
+
+var _wski18nResourcesDs_store = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x97\x41\x4e\xea\x40\x18\x80\xbf\x29\x5d\x34\xef\x25\xa4\xcb\xb7\xec\xf2\xad\x48\xbc\x41\x25\x40\x44\x77\xa0\x5b\x47\x10\x8c\x62\x43\x8d\xa0\x0b\x57\x1c\xc3\x43\x79\x00\x0f\xe0\x01\xbc\x81\xa6\xed\x6f\x40\x0b\x0e\x1b\x63\x35\xff\x97\x90\x6f\xc1\x7c\x65\x42\xda\xe9\x0c\x60\x9a\x37\xa3\x1d\x08\x81\x80\xc2\xfe\x1f\xd6\x12\xc8\xa7\x84\x27\xce\x3a\x93\x5f\xa3\x4d\x83\x01\x09\x09\x8d\xf5\xd7\x52\x14\xa5\x42\x64\xcf\x6e\x9d\x11\x63\x2c\xad\x77\xcf\xef\x84\x19\x29\xd3\x6e\x92\x9e\x0e\x93\x74\x28\x8b\x44\x07\xf8\xff\x92\x93\xf7\x75\xc6\x4c\xb1\x1c\xd1\x77\xb6\x0f\x6b\xda\x19\x96\xb6\xbb\x35\xbd\x52\x7b\xc6\x35\x96\x0e\x3d\x67\xfb\x58\x6a\x2f\x98\x63\xe9\x72\xe8\x6a\xbd\xe3\x52\x3b\x61\x80\x65\x9f\x5d\x67\xfb\x54\x6a\x2f\x49\xb1\x1c\xb8\xe7\x5c\x9b\x94\xda\xab\x7c\xce\xcd\x2d\xda\xe7\x0f\x6d\xc8\x1d\xe7\x58\xf6\x18\x30\x65\xe6\xea\xfd\xdb\x4f\xfb\xf9\x56\xf7\xc8\xfd\x4a\xaf\x54\x13\x53\x28\xf8\xfb\xdd\x13\x51\x14\xa5\x72\x64\xeb\x43\x24\x8e\xc5\x8b\xc2\x46\xbe\xf7\xc4\xfe\x4a\x13\x8a\x23\x71\x2c\x5e\x14\x36\x32\xce\x13\xfb\xe2\x40\x1c\x8a\x23\x71\x2c\x5e\x14\x96\x45\xcb\xc8\xe1\xc3\xc8\x2f\x1b\x39\xa1\x98\x50\x1c\x89\xe3\xaf\xf9\x6f\x14\xe5\xa7\x53\x2b\x14\x66\xef\xff\xf6\xe6\xf3\xbf\xa2\x28\xbf\x18\xe3\xb7\xfa\xad\xe6\xf2\x40\x50\xc2\x93\x8d\xc0\xc9\x5b\xb0\x61\x23\x20\x63\xb3\x57\xf1\x3f\x96\x63\x75\x23\xa0\x28\x15\xe3\x35\x00\x00\xff\xff\x7e\xe4\x42\x91\x04\x18\x00\x00")
+
+func wski18nResourcesDs_storeBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesDs_store,
+		"wski18n/resources/.DS_Store",
+	)
+}
+
+func wski18nResourcesDs_store() (*asset, error) {
+	bytes, err := wski18nResourcesDs_storeBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1491519881, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesDe_deAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesDe_deAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesDe_deAllJson,
+		"wski18n/resources/de_DE.all.json",
+	)
+}
+
+func wski18nResourcesDe_deAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesDe_deAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5d\x5f\x73\xdb\x38\x92\x7f\x9f\x4f\xd1\x95\x17\x3b\x55\xb6\xb3\xfb\x74\x75\x99\x9a\x07\x4d\xec\xd9\x78\x93\xd8\x2e\xcb\x99\xdd\xa9\x9b\xab\x11\x44\x42\x12\xd6\x14\xc0\x01\x40\x3b\x8a\xd7\xdf\xfd\x0a\x00\x49\x91\x12\xfe\x92\x72\xb2\xf7\x14\x47\xec\xfe\x75\xb3\xf1\xaf\xd1\xe8\x06\xff\xe7\x07\x80\xa7\x1f\x00\x00\x5e\x91\xfc\xd5\x5b\x78\x35\x29\xcb\x82\x64\x48\x12\x46\x01\x7f\x21\x12\xe7\x50\x51\xfc\xa5\xc4\x99\xc4\x79\xb1\x79\x75\x62\x88\x25\x47\x54\x14\x9a\x2c\x86\xeb\x07\x80\xe7\x93\x5d\x51\xb7\x15\x85\xa3\xa7\xa7\xb3\x2b\xb4\xc6\xcf\xcf\x70\x7a\xba\xc2\x45\x79\x04\x0b\xc6\xa1\x12\x68\x89\xcf\x7e\xa7\x0e\x71\x31\x9c\x56\x91\x98\x73\xc6\xdf\x82\x03\xb6\x79\x6a\x65\xa5\x4c\x82\xc0\xd2\xc1\xda\x3c\xb5\xb2\x5e\x97\x98\xfe\x63\x45\xc4\x3d\x64\x05\xab\x72\xc8\xd8\xba\xac\x24\xa1\x4b\xf5\xd7\x1a\xd1\x1c\x0a\x42\x31\x10\x2a\x31\x5f\xa0\x0c\x9f\x39\x84\xa4\xe3\x58\xd5\x79\xc0\x7c\xce\x04\x06\x56\xc9\xb2\x72\xbd\xd0\x0e\x91\x15\x28\xc7\xf3\x6a\x09\x05\x7e\xc0\x85\x1f\xcc\x42\x68\x05\x44\x95\x5c\x31\x4e\xbe\x9a\x8e\x34\xfb\x70\xf1\xdb\xcc\x81\x68\xa3\xb4\x42\x3e\x6a\x7b\x4d\x6e\x2e\x61\xf6\xfe\x7a\x7a\xe7\xc2\xdb\x23\x0b\x81\xfd\x7a\x71\x3b\xbd\xbc\xbe\x8a\xc0\x6b\x29\xad\x90\xf3\x4d\x89\x84\x80\x0c\x73\x49\x16\x6a\x08\x61\xc8\x56\x38\xbb\x27\x74\xe9\x80\xf6\x71\x58\x45\x7c\xa6\x68\x5e\x60\x90\x0c\x08\x25\x92\xa0\x82\x7c\xc5\x20\x30\x7f\xc0\x1c\x32\x46\x29\xce\x14\xf4\x5b\x78\x7a\x3a\xc3\x9c\x3f\x3f\x3b\xe4\x26\xc3\x58\x95\xb9\x41\x1c\xad\xb1\xc4\x1c\x10\x5f\x56\x6b\x4c\xa5\x80\x75\x25\x24\xcc\x31\x20\xb8\xc7\x1b\x78\x40\x45\x85\xa1\x44\x84\x6b\x2c\xc4\x97\xc2\xa9\xd3\x50\x34\xab\x6a\x13\x4a\x99\x34\x1d\xea\x10\xba\x0d\x86\xb3\x2a\xf7\x0b\x22\x05\xce\x95\xf5\x4b\xc4\x05\xde\x42\x06\xdb\x2d\x86\xd3\xde\xdb\x19\xbf\x87\x47\x22\x57\x40\xd1\x1a\x8b\x12\x65\x58\xb8\xba\xbb\x8d\xd4\x0a\x5a\x10\x21\x01\x53\x49\x24\xc1\x02\x08\x05\xb9\xc2\x90\x55\x9c\x63\x2a\xb7\xcc\x0e\x31\x91\xcc\x81\x51\xc0\xe6\x12\xd5\xbc\x1a\x90\x2d\x00\x3d\x20\x52\xe8\xe7\x5b\xfd\x13\x06\x44\x3a\xa2\x55\xc5\x25\x96\x20\x39\x59\x2e\x31\x17\x27\x80\xf4\x78\x52\x7f\xd0\x1c\x78\x55\x6c\xdf\x98\xe3\x25\x11\x92\x6f\xf4\x82\x87\x82\x56\x1b\x0d\x6b\x55\x56\xad\xbf\x54\xaf\xbf\x47\x40\x04\xa8\x05\x10\xa9\x0e\x4d\x72\xf8\xb3\x42\x05\x59\x10\x9c\x6b\x8c\xa0\x1d\x87\x20\xa5\x37\x71\xdb\x6d\xd4\xdb\xb5\xef\x06\x8d\x70\xfd\xbf\xe7\xe7\xa3\x71\xad\x9e\x2e\xc4\xfa\x22\x17\x9d\x2e\xde\xf2\x69\xa6\x0e\x8a\xd3\x3b\x8a\xe5\x76\x8f\x4f\x5b\xe7\xf5\x0d\x49\x2b\x7d\x60\x4e\x29\x51\x76\x8f\x96\x11\x33\x4a\x4b\x68\x5f\x3f\x09\xcd\xd5\xc4\x66\x96\x01\xa1\xda\x05\x35\x2c\xae\x05\xd4\xc7\x62\x15\x72\x49\x4d\x77\x2c\xf7\x96\x1b\xdd\xb4\xfa\xe7\x98\xbe\x93\x8e\xe3\x55\x07\xed\xaf\x30\x1a\x67\xfb\x7b\x8a\x52\xa9\x68\x56\xd5\x7e\x26\x34\xd7\x0e\x29\xc7\x06\x6a\xa1\x57\x9f\xa0\x12\x61\x3e\xab\xb8\xa7\xa7\x33\x76\xff\xfc\x6c\xd8\x70\x0e\xf3\x1a\xa6\x9d\x51\x9c\x83\x24\x86\xd3\x2a\xd2\x30\xa8\xf9\x11\x3f\x06\x3a\x9a\x95\xd4\xe1\x15\xe9\x87\xc9\x66\x0b\xf3\x45\x99\xad\xd6\x6d\x80\xd9\x6c\x9c\x56\x91\x55\x99\x6b\x5b\xe8\xfd\xa1\xd0\x9b\x96\x9a\xf7\x04\x18\x87\xd6\x54\x0d\x20\x59\x00\x91\x90\x33\x6c\x16\x04\xcd\xe4\xd0\xe9\x20\xd0\xde\x66\xa9\x25\x24\x36\x8a\x8b\xcb\xdb\x24\x86\x69\x48\x93\xf8\x38\x9d\xee\x86\xbf\x03\x77\x29\xbc\x06\x52\x84\x89\xd6\xb1\xb2\x78\x4d\xb3\x64\x72\x80\x59\x5c\x5c\x8e\x1d\x6d\x81\x25\x0e\x58\x65\x87\xc8\x6b\x98\x9a\x36\xd1\x36\x2e\x2e\xaf\x79\x0c\xd3\x90\x9e\xe3\xe3\xf4\x38\x09\x45\x11\x5a\xc4\xf7\xe9\xac\x70\x57\xac\x76\xf7\xb6\x1e\x53\x8e\xa5\x8e\x1d\x9d\x81\x8e\xf5\x3c\x8a\x7b\x28\x39\x2b\x31\x97\x1b\x10\x58\xc2\xe9\x69\x4b\x7b\xa4\x06\x39\xa6\xa2\xe2\x58\xfb\x62\xea\xc1\x76\x05\x23\x02\x4a\x8e\x33\x9c\xab\x39\x7e\x03\x08\x7e\x7f\xf5\xe6\xf7\x57\x0e\x7d\xbf\x83\x22\xe9\x8e\x6c\x63\x4b\x87\x8f\x39\xda\x87\x4d\xc2\xb7\xaa\xcf\xf1\x82\x63\xd1\x7a\x6e\xcd\xda\xea\xea\x25\x4e\x72\xef\xc8\x6a\xb8\x9c\x5a\xa6\x0e\xba\x01\x80\xae\xf1\x68\x18\x1a\x44\x9c\x83\xa8\xb2\x0c\x0b\xb1\xa8\x8a\x62\xe3\x1b\x8e\x21\x46\x8f\x47\xd2\xba\x30\xe2\xad\xd7\x1d\xe9\xd2\x79\x56\xea\x30\xdc\x3e\x9d\x67\x4a\x0d\xc3\xed\xd3\x59\xe1\xee\x56\xed\xcc\xbb\x6d\x31\x8c\xa4\x1a\x74\xf5\xe6\x91\xac\xcb\x02\xab\x31\x87\xf3\x66\x6b\x2b\x11\x57\xeb\x4d\x8e\xcb\x82\x6d\xd4\x23\x87\x12\x87\x42\x3f\x48\xcf\x85\xbc\xd2\x63\x74\x1b\x49\x87\xf7\x77\x77\x37\x20\x24\x92\x95\x80\x8c\xe5\x66\x57\xa7\xfe\x38\x58\xef\x4e\x14\x6a\x0f\xe3\x6e\x77\x12\x3a\xc2\xa5\x77\xa2\xb3\x0f\x17\xbf\xc1\xaf\x93\x8f\x9f\x2f\x66\x4a\x89\x35\x72\xb5\x41\x2c\xb7\x55\xf4\xec\x97\xcb\x8f\x17\x33\xc8\x18\x55\xf3\x9a\x72\x05\xad\x70\x7f\x9f\x5e\x5f\xf9\xb5\x18\x00\xb4\xa3\x10\x65\x12\x9f\x4a\x76\xda\x00\x33\x2e\x14\xf0\xf9\x35\x5c\x5d\xdf\xc1\xdd\xed\xe4\x6a\xfa\x71\x72\x77\x01\x77\xef\x2f\xe0\x68\x83\xc5\x11\x4c\xae\xce\xe1\x88\xb2\xa3\x33\x80\xbb\xf7\xd7\xd3\x0b\x98\xdc\x5e\xc0\x2f\x97\xff\xbc\x38\x87\x77\x1f\x2f\x61\x72\xfb\xb7\xcf\x9f\x2e\xae\xee\x8c\x1d\xa6\x8d\xe2\xe6\xc5\x9b\x5e\xfb\x40\x04\x99\x93\x82\xc8\x0d\xcc\xa6\xef\xae\x6f\x2e\x66\x3f\xc2\x06\x0b\xf8\x09\xc4\x0a\x71\x9c\x9f\x00\x65\xf0\x13\x94\x9c\x3c\x20\xe9\xf2\x70\x06\x82\x59\x5b\x44\x54\xeb\x35\xe2\xe4\xeb\x76\x60\xe5\x58\x22\x52\xb8\x56\x03\x37\xbd\x15\x9e\xd0\xac\xa8\x72\x0c\x65\x35\x2f\x48\x56\x6c\x6a\xcd\xf6\xa2\x84\x1c\x8b\xaa\x70\x35\x76\x22\x88\xfd\x68\xe9\x8b\xc1\x50\x74\x0b\xc2\x85\x84\xd9\xf4\xc3\xe5\xcd\x0c\x68\xb5\x9e\x63\xde\x5f\x59\x39\x5b\x87\xb5\x1a\x83\x68\x55\x91\xd1\x62\x03\x1c\xcb\x8a\x53\x98\x7d\xbc\xfc\x74\x79\xe7\xc7\xca\x58\x51\x98\xa8\xbe\x43\xc3\x11\x80\x56\x05\x1b\xcf\xca\xd5\x2d\x9b\xc7\x81\xd0\x92\x39\x7c\xa9\xa9\x49\x44\x88\x69\x8f\xc1\xde\x93\xd5\x6e\xc8\xaf\x61\x8f\x24\xe0\xda\x29\x5a\x65\x94\xd6\x9d\xd4\xb3\x4a\x82\xef\x16\x04\xf0\x6e\x17\xcc\x3b\xa3\x4a\xae\x0c\x10\xd3\x27\x10\x95\x5c\x45\x6c\x18\xfc\xbc\x11\xef\x3d\xb9\xb9\x84\x15\x13\xd2\xa8\xfc\xa3\x7e\x8d\xfe\x6f\x26\xf4\x54\x12\xf5\x4b\x1d\x18\x26\x26\x50\x95\x68\xa1\x03\x89\x8a\xb0\x65\x8b\xba\xb5\x89\x81\x8c\xb4\xa7\x8f\x3f\x52\xfc\x03\xe6\x42\x2d\x50\x5b\x84\xfa\x97\x24\x25\xfc\x28\xf6\xb3\xb3\x4a\xae\xd4\x6c\x99\x69\x97\xb0\x12\x98\x6f\x03\x2c\x2b\xf4\x80\xed\x3e\xc7\x8f\x5a\x44\x73\x78\x1d\xe9\xaf\xbf\x88\x28\xfb\xbe\xd4\xea\x27\x35\x7e\xa0\x25\xf2\x5f\xe0\x3c\x1c\x31\x1f\x8b\x1a\xd1\x15\xb6\x16\xd8\x36\x61\x64\x2c\x20\x02\x60\xd0\xbc\x76\x2c\x5e\x8f\x9e\xda\xfa\x18\xf6\xcd\x0b\x8d\x98\xa5\x77\x88\x02\xef\x63\xa8\x47\xcd\xd4\x11\x10\xb1\x73\xb5\x86\x8a\x9f\x9e\x0d\x79\x52\x97\x89\x97\xb0\xcb\x93\x32\x47\xc6\x4b\xd9\x61\x49\x9c\x09\xd3\xe4\xf4\xb9\xac\xa2\xcc\x0a\x92\xe3\x05\xaa\x8a\x66\x01\x61\x0b\xd5\x90\xf5\x6f\x0a\x90\x14\x05\xcc\xb1\x9a\x9c\x72\x77\x16\xd3\x10\x24\xb7\x4a\xcd\x0e\x75\x07\x50\xae\x90\x84\x0c\xd1\x48\x75\x12\x50\xdc\x31\x65\xff\xe8\x5b\x06\xc7\xde\xb6\xff\x7a\xb3\x6b\x34\x41\x20\x4f\x47\x75\x9c\x60\x8a\x8e\x26\x0a\x00\xd5\x3d\x23\x88\xd5\xd0\x79\xe0\x42\xe7\xf5\xbb\x54\x1e\x28\xb5\x2d\x8c\xd1\xac\x4b\xe7\x98\xee\xee\x29\x7b\x74\x81\x34\x4f\x03\x36\x9a\x57\xa4\xc8\x83\x16\x32\x54\x31\x50\xf5\x5e\x22\x0e\xb1\x21\x8e\x0b\xa8\x6e\xd9\x08\x35\xdb\xf7\xb4\x14\xa8\x48\x98\x88\x2c\xb7\x7b\xec\x1a\x28\xfb\x74\x51\x46\x8b\xed\xa9\x7d\x6a\xbb\xa6\x45\x11\xde\x46\xed\x10\x79\x74\x9c\x5d\x4d\x3e\x5d\x4c\x6f\x26\xef\x2e\xfc\x69\x73\x5d\xba\x40\x73\x16\x4c\x27\xc0\x6d\xe5\xc3\x82\x14\xc6\xb3\x52\x7f\xa4\x07\xc4\x93\x01\x03\x0a\x72\x8c\xf2\xee\xca\x7f\x00\x15\x07\x40\x7a\xd3\x08\xf4\xe2\x8a\xf2\x9c\x63\x21\x34\x46\xbd\x11\x8a\xce\x1c\x88\x00\xb0\x2a\xf0\x8f\x9d\x6d\xb7\x79\x8b\x47\x4e\xea\xb3\xaf\x8a\x87\x9d\xac\x34\x8c\x40\xe0\x40\xa7\x43\x05\xa3\x05\x86\xca\x1e\x04\x32\x8d\xa4\x28\x5c\x41\x9d\x0e\x45\xa0\xeb\x74\x48\x07\x9e\xee\x84\x11\xbc\xde\x94\x61\x37\x59\x62\x09\x5b\x08\x27\x9b\xfd\x7c\x80\x88\x90\xcd\x7a\x24\x01\xa3\x75\x69\x07\x5a\x2d\x02\xc2\x7f\x10\x6b\xf8\x93\xed\xe6\xe6\x73\xba\x5a\x9a\xd2\x84\xe6\x3d\xde\x56\x97\x2a\x38\x5d\x49\x4e\xf0\xc3\x28\xfb\xc5\x60\x78\x0d\xd8\x7f\x7f\xe5\x90\x3e\x3d\x9d\x19\xfd\x23\xcc\x18\xe2\xf6\x65\xf5\x50\xfc\xe8\xeb\x88\xbb\x54\x01\x63\xd6\xe4\x23\x4c\x19\x46\x88\xca\xef\x49\xec\x88\x4e\xb6\xd8\xcc\x1e\xc5\xd8\xcf\xbd\xd1\x50\xe3\x72\x7a\x52\x40\x43\x5b\x7a\x83\x3e\xa2\x61\xc2\x08\x51\x59\x3e\x89\x0d\xe3\x64\xf3\x4e\x10\x81\x99\xe1\xff\xc5\x94\xb0\x64\x32\xd5\x58\x56\x16\x5f\xd6\x8f\x6f\x05\xea\x50\x84\x16\xa0\x2d\xe9\xd0\xf5\x27\x88\x10\x95\x07\x94\xba\xfa\xb8\xd8\xfc\x19\x40\x3e\x97\x69\x87\x28\x2d\xc6\xba\x17\x82\x77\xbe\x41\x12\x44\x7a\xbe\x8d\xc9\x91\x7f\xa1\x64\x9b\x78\xf0\xef\x7a\xba\xac\x3b\xc5\x41\x8e\x96\x87\x20\xb9\x76\xd1\x4c\xed\xb7\x33\x54\x14\x9b\x9e\xa7\x8b\x16\x12\xd7\xab\x84\x5a\x37\x88\x33\xd1\x20\x01\x21\x42\x85\x9e\xdb\x38\xc7\x0b\xc6\xeb\x44\xbe\x04\x25\x42\x18\x81\x13\x76\xcd\x16\x7b\xbc\xde\x23\x0e\x6c\x8c\x54\x97\x15\xf9\x7d\x70\x6b\xd4\xd0\x39\x8e\xea\x85\x54\xb3\xc1\xf4\xfc\x03\x20\x2e\xc9\x02\x65\xd2\xa5\xa6\x9d\x36\x1e\xf6\x04\x1e\x75\x30\xd3\x6c\x50\xdf\x5d\x7f\xba\xb9\xbe\x52\x9d\xbb\xce\xdc\x40\xca\xae\x2c\xbb\xc7\xfc\x04\x08\xab\x8b\x61\xe6\x48\xac\x54\x73\xa4\xa8\x94\x22\xe7\x7a\xba\x23\xc7\x99\xe0\xa4\x44\x64\x6c\x5d\x32\x8a\xa9\xec\xa5\x10\xae\x89\x10\x84\x2e\xcf\xe0\x9a\xe2\x0e\xc9\x71\xef\x65\x18\x6f\x65\xbc\x6e\x2b\xce\x44\x89\x33\x5d\x4a\xe3\x49\x7d\x7a\x59\xb9\x81\xa9\x77\x89\x29\xe6\xca\xa9\x1a\x36\xb9\x06\xd8\xed\xc5\x23\x48\xac\xfe\x50\x6f\xa3\x46\x18\xa3\x7f\xac\x85\xab\xe8\x52\x59\x47\x51\x83\x7a\xb9\xd3\x2d\x0b\x88\x8c\x93\x52\xc2\x71\x2b\xf4\xb5\x59\x79\x74\x5f\xd9\xa6\x88\x35\x45\x6a\x39\xe1\x38\x93\x8c\x6f\xce\x7e\xa7\x77\xed\x06\xbd\x57\xbe\xdb\x01\x67\x0b\x78\x14\xf7\xcd\x63\x71\x02\x82\x55\x3c\x33\x19\x21\x4a\x11\xd8\x57\x84\x50\xc9\x60\xc3\x2a\xd3\x14\x80\xe9\x03\xe1\x8c\xaa\x66\x74\x2d\x7e\x9e\x86\x3f\xd2\x89\x5e\xf5\xcf\xfd\x45\xf5\x0c\x7e\xd5\x5d\xbe\x7d\xbc\x37\xa8\x62\xc6\xd4\xb7\x91\xed\x7c\x6d\x1d\x2b\xda\x6e\x15\x51\xc1\x31\xca\x37\x66\x0f\x21\xce\x00\xce\x8d\x27\x46\xa4\x29\x96\xc3\x92\x6f\x5c\xb5\xd9\x83\xe1\x9c\xca\xf5\xdf\x5f\x9b\xa9\xee\x56\x49\x25\x22\x83\xa0\x9c\x4a\x19\x1b\x83\xb8\x57\xaf\xc2\xa8\x39\x2c\x7a\xec\xf4\x77\x24\x1d\xfd\xdd\xa3\xde\x08\x50\xab\xa2\xe7\xec\x91\x16\x0c\xe5\x38\x87\x6d\xc9\x3c\xb9\x9e\x82\x90\x88\xeb\xaa\xab\xb2\x3c\x83\xcf\xf4\x2b\x29\xbb\xcd\x45\x73\x60\x25\xa6\x4d\x68\xf5\x5f\x38\xd3\xe7\xf1\xff\xcc\x58\xee\xb9\x8b\xe0\x85\x84\xc5\x6e\xca\xd4\x30\xa9\x78\x51\x22\xb9\x52\x83\x64\x7a\xfe\x61\xc8\xb6\xcc\x8b\x62\x55\x65\x6a\x0a\xbf\x17\x6d\x71\xb1\xc0\xd4\x44\xa5\xf7\x06\x6e\x8c\x4e\x83\xe1\xec\xf5\x93\x9c\xb3\x8e\xff\xa6\xfa\x7b\x7f\x6c\x06\xf5\x49\x41\xf0\xa9\xc0\xca\x8d\xe2\xaf\xcb\xe4\x39\x16\x25\xa3\x02\x9b\x59\x5a\x01\xc6\x2a\x92\x80\xe3\x1e\xbb\xcd\xb0\x39\xe0\x94\x37\x1c\xd3\x63\xb5\x8a\xfe\xed\x2b\x29\x4b\xf5\xc2\x83\x9a\x2d\x86\xdf\x2b\x5e\x22\xce\x47\x48\x0f\xb2\x87\xbc\xed\xba\x58\x3b\xec\x6e\x37\x84\x56\xc0\x05\xe1\xb8\x21\x01\xfc\xe0\xce\x7a\xb7\x10\x06\xa6\x9f\x1e\xc7\x30\x7f\x2d\x02\xc2\x1b\xe6\xa8\x59\x71\x0e\x6f\xfa\x95\xcd\x6f\xb6\x3d\x51\x1b\x89\xe4\x0a\x91\xe4\x11\x31\x90\x61\x98\xa1\x80\x72\x8d\x1a\x8e\x29\x37\x84\xdf\x75\xab\xdf\x1c\xea\x9d\x9e\xd6\x49\xd0\xad\x47\xd6\x49\x96\xe4\xcb\x07\x54\xe8\xac\x3a\x43\xdc\xd9\xee\x18\x0d\x18\xd7\x0a\x04\x0e\x0e\x0f\x23\x23\x2e\x0a\x3f\xae\xb7\x46\x81\x44\xc5\xe2\x1b\x88\xf4\x70\xbc\x8d\x33\x36\x22\x5f\xf3\xf6\xe3\xe7\x0d\xe0\xb8\xb8\x3c\xa2\x03\xd0\xe3\x02\xf4\xe3\xda\x2c\x0a\x24\x2a\x4c\x9f\xde\x66\x3e\x4e\x67\xb0\xde\x3f\x51\x74\x29\x82\x5b\x69\x39\xd2\x76\x61\x84\x60\xb8\x3e\xdd\x68\x2e\x2e\x5f\xd0\xde\x6f\xb3\x1d\xa2\xb8\xd0\xfd\x38\xcb\x45\x81\x44\x05\xf0\xd3\x0d\xe8\xe3\xf4\x87\xf1\x03\x2e\xc7\x3e\x5d\x7a\x1c\xbd\x61\x7d\xa9\x50\x7a\x12\x7e\x40\x7d\x42\x1f\xd8\x7d\xbf\x11\xd5\xdf\x6d\xa9\x1c\x56\x6b\x96\x2e\x64\x31\x49\x37\x18\xe7\x6d\x9e\xb9\x7e\x58\xa7\x73\x67\x8c\x2e\xc8\xb2\xe2\x11\xfb\xf4\x6f\x24\xfc\xbb\xfa\x16\xcd\x2b\x1d\xe4\x24\x61\x20\x98\xb5\xe5\x1b\x2c\x6d\xbe\xd9\xe4\xdd\xdd\xe5\xf5\xd5\x1f\x57\x93\x4f\xce\x44\x35\x0f\x43\x20\x46\xdf\x70\xc6\x86\xe9\x77\xe9\xed\x85\x53\xed\x85\x32\x03\x0a\x2e\x23\x99\x23\xeb\x2d\x6d\x68\x43\xca\x2d\x43\x38\xf6\x32\x94\xbd\x8b\xd6\x74\xec\x14\x04\x56\x70\x52\x75\x06\xb5\x05\x6d\x1e\xfe\x59\x31\x5d\xc6\xbb\x50\x13\xc9\xa6\x91\x0e\xa6\xd0\xc2\xb5\xed\x3d\xac\x0c\x6f\x66\x5e\xfc\x25\x6f\x3e\x0e\x67\x40\xa0\xf5\xba\x67\xc6\xdf\x7e\x7e\x9e\xa5\xd4\x59\x25\x41\x0c\x54\x42\x37\xf9\x01\x34\xd9\xc5\x71\x94\x1f\x7a\x8b\x62\xbd\x55\xae\x7a\xaa\x71\x0d\x66\xf3\xd0\x1f\x86\xee\x9e\x5d\xf7\x9d\xe5\x60\xc8\xd9\xc7\x1a\x13\x1f\x33\xf1\x92\x3d\xac\xd4\x20\x59\x18\xc6\xa3\x0c\x2b\xb1\x1e\xf6\x63\x34\x89\xc5\x08\x16\xfc\x0c\xd2\x21\x01\x20\xe4\x3c\x95\x98\x8a\x7e\x6d\xbe\x8e\x2b\xd5\x41\xad\x14\x37\x29\x1a\x29\x6e\x13\xbd\x0d\xf7\x29\xcc\x9c\x70\x05\xf9\xb8\x52\x6f\xda\x82\x8e\xdb\x61\x8f\x90\x10\x61\x55\x50\x08\x38\xef\xa7\x4b\x1f\xee\x1d\x0e\x20\x22\xae\x1d\x5e\x48\xff\x71\xe8\x11\xa3\x5b\x22\x3e\x76\x70\x07\x20\x3c\x4a\x70\x8c\xf2\x91\x4a\x44\x42\x1c\x60\x30\x35\x31\xe4\x97\x1b\x4c\x7e\x09\x23\xfb\xe1\x41\xd4\x1f\x88\x1e\x9c\xde\x07\x75\x80\x04\x80\x28\x05\x7a\x8b\xf6\xde\x9d\x2b\xad\x04\xb9\x29\xb1\x73\xdf\x3f\x0e\x33\x70\x0a\x51\x5f\x14\x1b\x3c\x84\x68\xe8\x7c\x61\x70\x73\x05\x22\xf2\xdd\x25\x61\xa3\x0c\x18\xb2\xbe\xcf\xd8\x6c\x85\x9b\x1c\x8a\x78\x9f\x79\x00\x50\xdc\xa8\x40\xa9\x17\x6a\xbb\xf8\xa2\x02\xca\xb5\xda\xe9\xf1\x64\x0b\x63\x6c\x38\xd9\xb0\xf6\xe2\xbd\xb4\xc1\x1b\x19\x4d\x4e\x45\x8e\x8b\x24\x27\x37\x89\x8b\x2f\x2a\x5e\x9c\xdc\x24\x1e\x46\x47\xce\x9b\x0e\x11\x79\x07\x54\x9f\x26\x2e\xe0\xd5\x09\x2b\xa5\xcf\x8b\x31\x18\x5e\xf3\x19\x80\x43\x1e\xe8\x0d\x41\x74\x86\xe7\xbd\xd6\xee\x10\x44\x04\xe7\x93\xbb\xa3\x95\xc9\x9e\x94\xea\xd3\xd2\xa7\x61\x37\x0a\x9f\xdc\x81\x1d\x4c\xbe\xc8\xbd\x57\xd1\x3e\x4d\x5c\xdc\x3e\xd9\xa8\x2e\xbe\xa8\xe8\x7c\xb2\x89\x3c\x8c\xfe\xd8\xbc\x7f\x21\xde\x23\x4b\x8f\xcc\xd7\x9c\x2f\x15\x98\x4f\x81\xb7\x2a\xff\x8e\x55\x45\xae\xa7\xfc\x05\xa1\x39\x1c\xad\x11\xa1\x47\xb0\xc6\x72\xc5\x74\x82\x65\x07\xca\xa1\x5f\x0a\x42\x9c\xfd\xf6\x67\x39\xbd\x90\xb3\x72\x93\x6e\xac\x28\x2c\xab\x5a\xbf\xec\x86\x7f\x76\xee\xcf\xd7\xee\x1e\xe3\xfb\xcb\x66\x50\xc9\x43\x20\xc7\x94\x46\x0f\xad\x27\x72\xb2\x5a\x85\x5a\x5f\x44\x54\x65\xc9\x78\x67\x48\xf2\x8a\x4a\xb2\x76\xc5\xff\xd2\x30\xdc\xde\x70\x7d\x66\x5e\xd3\xeb\xbb\xd1\x10\x9c\x7d\x25\x65\x9b\x55\x0e\x1c\xff\x59\x11\x8e\x45\x9d\x3c\xad\x53\xbf\x74\xce\xaf\xe1\xb9\x57\x7d\x18\x7f\x29\x0b\x92\x11\xe9\xfc\x26\xd3\x0b\x09\xb3\xbe\xd8\xdf\xd1\x03\x6a\xc7\x79\x0d\x08\xa7\xa7\x6b\x3d\x15\xb0\x06\xd9\xdc\x64\x57\x15\xc5\xe6\xb4\xff\x61\x07\x7d\x7c\xb7\xc2\xa0\xe9\xb3\x02\x09\xd7\x64\x77\x78\x39\x8e\xe3\x20\x8c\x24\x98\x53\x1d\x40\xa2\x49\x50\x25\x6b\xb4\xc4\x50\x22\xb9\x02\x46\xeb\x1f\x57\xd5\xdc\x79\x44\x94\x04\x12\xa5\x48\x7b\xad\xb0\x9a\x56\xf7\xbc\xe6\x48\x45\x02\x20\x51\x8a\xec\x1c\x79\x80\xc0\x7f\x56\x98\x66\xb8\x3b\xdf\xb7\x2e\x61\xa4\x5e\x69\x98\x76\x35\x57\x18\x66\x1f\x2e\xaf\xce\x67\x4d\x53\xf7\x87\x25\x1c\xe3\x2f\x68\x5d\x16\xf8\x2d\x88\x47\xb2\x90\x6f\xeb\x6b\x6e\x4e\x80\xb2\x1c\xff\x4b\x34\xff\x7f\xed\x52\xf9\x60\xf8\x4e\xf5\xbb\xfd\xb4\x06\xc7\x54\xf2\x0d\x94\x8c\x50\x09\xc7\x8b\x8a\x9a\x5f\x19\xdf\xeb\xe3\xf5\x82\xa6\x21\x1e\x57\x98\x02\x32\xdf\x65\x9b\x17\xd8\xf7\x46\x2f\x26\xd2\xe3\xa0\x1e\xe6\x0c\x78\x18\x96\xd3\xf6\xaa\x09\x59\x25\xdb\xbb\x2c\x09\x85\x35\x29\x0a\x22\x70\xc6\x68\x2e\xea\xba\xb0\xc7\x15\xc9\x56\x5d\x63\x11\x01\x12\xf3\x35\xa1\xaa\xdb\x7a\xec\x7c\x10\x78\xa7\xf2\x6b\xf4\x85\xac\xab\x35\xac\xf1\x9a\xf1\x4d\x57\xc8\xa7\x9f\xb5\xef\xb5\x85\xf4\xe8\x98\x82\x12\x54\xa5\x60\x4b\x10\xe4\x2b\x1e\xab\x4c\x1c\x8e\xbd\xc4\xa7\x60\xfa\xd3\x68\xfe\xa9\x68\x97\xca\x71\xc6\xc7\x1e\x41\x5f\x79\xaa\x04\x3e\x98\xd2\x09\x73\xdf\x2a\x90\x05\x20\x68\x51\x3a\xcf\x8f\x2b\x5a\x60\x21\xb6\x77\x6b\xa1\xe6\x5a\x12\xd7\x88\x3c\xb8\x18\xeb\xcb\x44\x5c\x2e\xdb\xfa\xed\x87\xba\xad\xd6\x05\x68\x55\xd0\x7f\xb7\xec\x1e\xd4\xc8\xbb\x6a\x7d\x78\x81\x84\x8e\x7a\x94\xc6\xe6\x73\xec\x90\x47\x04\x61\x4d\x13\xc7\x05\x62\x1b\x5a\xcf\x8e\x32\x88\xb8\x47\x36\xa8\x70\x7b\x60\xb1\xf6\xc0\xed\x6b\xad\xea\x4b\x6e\x61\x53\x44\x78\x63\x48\x06\x28\x10\x47\xaa\x89\xe2\x37\xa3\xed\x44\x91\x31\x9e\x6b\x25\x8f\xea\x98\xd6\x80\x77\x8f\x07\x74\x2e\xf1\xfd\x89\x4b\xb1\xbb\x83\x70\xc7\x9d\x1b\x5a\x00\x49\x85\xae\xd6\xca\xe7\xe7\xd7\xce\xa8\xca\x41\x45\x44\xc5\xc3\x6a\x69\xb1\xa1\x47\x27\x9b\x3b\xfd\x57\x75\x38\xb6\x14\xb5\x5f\x1e\xd5\x55\xdc\x3c\x71\x3d\x47\xf3\xea\xef\xfd\x6d\x55\x1d\xd1\x6f\x62\xe1\xe2\x94\x6b\x16\xbd\xed\xd5\x7a\x07\x54\x75\x18\xb8\x3d\x6f\x88\x15\x85\x4e\xec\x22\xb4\x62\x95\x28\xcc\x17\x14\x95\xd3\xb2\xc6\x42\x6c\xaf\x40\xaf\xeb\x17\xd5\x3a\x54\x51\xba\xdd\x72\xb9\x26\xe2\xf1\xb8\x56\x75\x6f\x14\x6c\xd0\x61\xdd\xa5\xb2\x1f\xac\x53\xe5\xb1\xbe\x93\xbc\x38\xcd\xf4\x85\x63\x5f\x88\x33\x5d\xc9\x4e\xeb\xd4\x50\x17\x50\xf5\x1b\x44\xf5\x2e\xe7\xb8\xf3\xf3\x58\xc5\xfc\x4e\x27\x2d\xe1\x5b\xe8\xcf\x15\xaa\xe1\xdd\xb3\x4f\x0c\xe7\x18\xb7\xab\x5d\x6b\x0e\xe9\x7a\xb9\x40\x07\xba\x5f\x7b\x70\x07\x70\xc1\x7c\x98\x8e\x83\x30\xf3\xea\x6a\x5b\xda\x6d\xf6\x1c\x9b\x7a\x78\xdf\xf1\x58\x98\xd3\x2a\xb2\x7e\x81\xae\xba\xa6\x18\x8f\xac\xb1\x90\x68\x5d\x0a\xc0\x88\x17\x04\xab\xcd\x09\xa2\x30\xfb\x7c\x73\x77\x3d\xfb\x11\xd6\x18\x89\x8a\x9b\x2b\x01\x7a\xdb\x3e\x41\x68\x86\xe1\x6e\x75\x02\x7f\xf9\xeb\x09\xfc\x1d\x51\xf8\xeb\x7f\xff\xd7\x5f\x1c\x6a\x7f\x2b\xe9\x43\x5f\xbd\x40\xb2\x15\x3d\xbd\xbc\x7a\x77\xf1\x2d\xdf\xfc\x10\xc2\x23\xbc\xfd\xb6\xa7\xc4\x7b\xfc\x3b\x2c\x76\x21\x92\x95\x50\xd6\xd3\x98\x89\x05\xcc\xa6\x17\xef\xae\xaf\xce\xa7\x33\xa8\xb5\x76\x09\x8b\x61\x75\x08\x45\x5c\xb6\xac\xfd\xc9\x53\xec\x83\x00\x5a\xba\xee\x72\x18\x82\x34\x44\xa5\x4f\x97\x57\x9f\xef\x2e\xa6\x33\x58\x13\x5a\x49\x3c\x42\x25\x2b\xd2\x10\x95\xde\x5f\x7f\xbe\x9d\xce\x60\xc5\x2a\x3e\x42\x9d\x3d\x94\x21\xaa\x9c\x4f\x7e\x9b\xce\x20\x47\x9b\x11\x8a\xec\x60\x04\x32\xed\x9b\x9d\x81\xce\xb9\x3e\xea\x7f\xe1\xfc\xcd\xf6\x0b\xe7\xc1\x6c\xfa\x58\x1c\x67\x1a\xf5\xfe\x57\x75\x4d\xb5\x68\x4a\x3e\x7b\x3c\x86\x3b\xa1\xdd\xf6\xdd\xf7\x54\x3d\x12\x40\xec\xcd\xd3\x9e\xf9\xe8\xc8\xac\xce\x67\xca\x6a\x38\xdc\x9c\x9c\xe4\xce\x12\x87\x48\xee\x18\xd1\x44\xa4\x8a\xeb\x71\xa4\x8a\x80\xed\x33\x22\x80\xe9\x75\x1c\x15\x03\x24\xbb\x80\x7c\x0a\xd5\xb3\xfc\xe5\x79\xc2\x5b\x3b\x78\xec\x62\xda\x6f\x62\xb5\xed\xd2\x7c\xb7\xd8\xfc\x10\xd3\xb6\x49\x18\x31\x6a\xc4\xbc\xab\x87\xc3\x21\x42\x5f\x4f\x16\x8f\xef\x20\xf7\x80\x9f\xb4\xa5\x55\x9d\xfe\x9d\x60\xc6\x14\x0c\x87\x1a\x0d\x73\xfc\x6b\xba\x39\x52\x45\x80\x6a\x93\x4d\xc1\x50\x1e\x35\x50\xd2\x81\x5c\x03\xa5\xa1\xe8\x04\xd1\x88\x39\x94\xd4\xfb\x83\x7e\x1d\x93\x67\xf0\x24\xe2\x44\x15\x5a\x1d\x8b\xd7\x67\x6a\x66\x6d\x5e\x2e\xba\xde\xca\xc2\x18\x2b\x50\x4f\xe5\x88\x2f\xc5\xf3\xf3\x60\xd9\x1e\x0c\xc7\x36\x14\x65\xee\xcc\x81\xe6\xa9\x3d\xb6\x27\xa1\xc0\xc8\x99\xd2\xd9\x3e\xb6\x32\x53\x06\x6b\xa6\x3f\x8f\x8b\x5c\xfb\xb2\x1e\x89\x3d\xf2\xcc\x76\xd6\xc4\xd0\xb0\xf1\x30\xb8\x5c\x2c\xf7\x85\xda\xbe\x7b\xb4\x5b\xef\xc1\x19\xd1\xd9\x12\x38\x52\xe3\xf4\xf1\xb0\x33\x29\xce\x3c\x75\x2e\x41\x4d\x09\x5c\xe3\x3b\x95\x9c\x3d\x90\x1c\xe7\x3b\xbe\x95\x67\x41\x8a\x45\x70\x7a\x3f\xed\xd7\x7a\xea\x14\x99\x78\x97\x27\xc4\xe9\x7a\xeb\x96\x6f\x57\x67\xcf\xdc\xe1\xe1\xf1\x0e\xdb\x05\xc1\x85\xce\x7d\x92\xb8\x6b\x0e\x97\xa4\x20\xdb\x80\xc0\xf3\x09\xe4\x44\x94\x05\xda\x98\x1b\x86\x14\xb0\xae\x90\xc0\xc5\xf0\xa8\x74\x08\x33\x39\x5f\xf4\x30\x4a\xa6\x20\x06\x55\xdc\xfb\xb8\xf9\x78\x1d\x93\x21\x83\x4a\xf6\x2f\x5f\x1e\xaf\x61\x1a\x5e\x50\xbd\xbd\x7b\x25\xc6\x6b\x98\x0c\xe9\x9b\x06\x4a\x24\x57\x27\x80\x68\xf3\x25\xa6\xb9\x29\xc5\x46\x34\xdd\xbd\x1b\x0e\x18\x52\xb0\x41\x68\x20\x53\xf5\x09\xf0\x5b\xc4\xdb\x53\x17\x6b\x27\x62\xfb\x1e\xc1\x59\x3a\x19\x66\xb8\x2e\x2e\x3b\xc4\x72\xc7\x15\xea\x4c\x6e\x2e\xd3\xab\x74\xfa\x4c\x51\x25\x3a\xaa\xa9\x9e\x9e\xce\xcc\xf5\x8a\x60\xbe\xa7\x39\x7f\x7e\x6e\x23\x2f\xfd\x74\x70\xd5\xdd\xab\xa2\xbe\x8c\x31\xba\x9a\x67\x9c\x8c\xb8\x4a\xab\x92\x1c\xa2\xcc\x2a\x80\x12\xae\x23\x9b\xdc\x5c\xc6\x14\x91\x29\xb2\xd8\x82\x26\x37\xa4\x83\x38\xae\xec\x28\xad\x83\x59\x99\xa2\x0a\x8e\x5e\xb2\x83\x1d\x46\x86\xf3\xd4\xdb\x6d\xf9\xe6\x69\x44\x3d\x4d\x9a\x9d\xf7\x39\xbc\x75\x2a\xd4\xa3\x63\x9f\xe6\x3f\xb1\x4e\xa5\x6e\xb6\x39\x12\x38\xb2\xc1\x7d\x9c\x51\x22\xb7\xbd\x44\x9f\xe3\x0d\x93\x1e\x00\x49\x54\xa4\xd3\x5d\x0f\xa1\x52\x00\xce\x9d\x7d\x35\xb9\xb9\xf4\xa6\x5d\xe9\xe7\xf1\x29\x50\xaa\x89\x8a\x98\x72\x8e\x58\x6e\x67\xf5\x84\x79\xdd\xbd\x45\xb7\x71\x42\xce\xa0\xbe\x93\x7b\x7b\x4b\xe3\xdb\xc6\x4a\xc2\xeb\x50\x8c\x04\xb6\x2a\x5c\x5f\xc8\x34\xeb\x54\x25\xea\xdc\x64\x05\x4a\x04\x64\xfa\x56\x69\x87\x4e\x71\xbc\x8e\xe3\x51\x05\xf3\x80\x61\x36\xb9\xb9\xfc\xe3\x66\x72\xf7\x5e\xa7\x89\xbb\x67\x0f\x0f\x83\xdd\x8b\xbc\xb9\x34\xa4\xbf\x5e\xdc\xfe\xec\xba\x9a\x6a\x87\xc8\x09\xb4\x3d\x5a\x37\x1f\x5c\x9c\xc1\x71\xf3\xd1\xd7\xf6\xfb\x8b\xae\x1c\xd5\x78\x7e\x6f\xa0\x60\xf6\xf3\x64\x7a\x51\xbf\xb7\x64\x9d\xcc\xe7\xc6\x1c\x26\xd0\x68\x8c\x14\x08\x1d\xa4\x61\x79\xa7\x0f\x35\x08\x83\x93\x42\x4d\xe4\x02\xaa\x78\x61\xe6\x09\x56\x62\xae\x99\xcd\x7f\xcd\x24\xee\x9f\x74\x22\x78\x7d\x9b\x0c\x35\x15\x99\x9d\x42\x2f\x4c\x0b\xdd\x98\xa9\xa2\x6b\x7b\x5f\xbb\xab\x68\xe5\xc1\x1a\x6d\x00\x15\x82\x25\xc4\x53\x5e\x4e\xac\x73\x52\x6a\xee\x2b\xaf\xa3\x38\x4b\x42\x4d\x4a\xc0\xd1\x1b\x67\x48\x26\xc8\x16\xe5\x09\x8b\x47\x64\xae\x7f\x8b\xb9\xc2\x3b\x92\xd9\x9e\x60\xd5\xbb\x76\xa4\xcb\x39\xe2\xf6\x92\x08\x18\xc7\x69\x42\x73\xa5\x60\x9d\x2f\xa7\x3f\xb5\x89\xcc\xc4\xdd\x7e\xe7\xc3\x7d\x84\x10\xc7\xed\xb1\x83\xb2\xdf\x01\xec\x90\x00\x63\x55\x66\xda\xe5\xeb\xdc\x31\x76\x5c\x7f\x25\x45\x0f\x85\x1b\x1d\x3a\x20\x74\xc1\x4e\x74\x4f\x37\xdf\x47\xd9\x8a\xc4\x45\x2e\x5c\xd3\xeb\x01\x05\x84\x5f\xa0\xc1\x32\xc3\xc1\xa4\x06\x98\x7c\x72\x28\x9a\x0e\x53\x20\xb1\x82\xe3\x37\x51\xfa\x26\xe1\x39\x57\xa7\x7e\x51\xa9\xde\x64\x34\x2e\x56\xdf\xdd\xf2\xac\x50\xf1\x18\x29\x6a\xa8\x9f\x75\xd8\x47\xcd\xc8\x25\x31\x7d\x26\x4d\x0b\x3b\x84\x6f\x4e\xd7\xd4\x19\xa2\xe6\x6c\xab\xfb\x59\x1d\x60\xd4\xf9\x25\xf1\x48\x66\x7b\x1f\xa9\x6b\x29\x51\x7f\x98\xa8\x2e\xd6\x3c\xd9\x9d\xf7\x4d\x2b\x27\x44\xce\x5c\x53\xc5\xb7\x91\x1d\x7f\x22\xf8\x3d\x6d\xf1\x1d\x15\xb2\x17\xe3\xeb\xd4\x14\xa8\x04\xee\x5f\xd6\xde\x5c\x2e\x67\x2a\xee\x5c\x6f\x13\xcb\x6d\x1f\x0b\xbe\xe4\xd2\x89\x27\x4b\xf4\x57\xcc\x5d\x55\xba\xfa\x91\x73\xf8\x5f\x21\x67\x39\x78\xfb\xd8\xee\x30\xdc\x7e\x74\x79\x03\xb7\x1f\xed\x2c\x3f\x37\x4d\xe5\x60\xdc\x3e\xb7\xe7\x4c\xbb\x39\x6f\x9c\x4c\x75\xa8\xdd\x24\xc1\x76\x32\x5f\xd5\x2e\x04\xa3\x6c\xe5\x8b\x7c\xc4\xb0\x7e\xcf\x33\xbb\x5b\xfc\x67\x85\x75\x25\x53\x86\x4b\x7d\x2d\xeb\xbc\x92\x8a\x29\xc3\x66\x11\x35\x77\x24\xeb\x0f\x68\xe1\x1c\x36\xd8\x99\x6c\x30\x04\xc9\xbb\xc1\x08\x5e\x4b\x63\x24\x98\x1c\x6d\x23\x7b\x55\x3b\x4a\x1b\xac\xef\xb0\x20\x62\xa5\xf4\x38\xf8\x7d\x38\xc3\x05\x47\x95\x8d\x23\x78\xc4\xf3\x7a\x92\x39\x01\x04\x1c\x3d\xc2\xfb\xbb\xbb\x9b\xde\xcf\x8c\x1b\x52\x21\x11\xcd\x11\x6f\x22\xfb\xa6\xa4\xf7\xdf\x20\x79\x85\xe1\xa7\x1e\x87\x82\xf9\xc9\x0e\x46\x19\xfc\x1b\x16\xa8\x10\x8a\x67\x07\x31\xb2\x2e\xfd\x3f\x4c\xe9\xa8\x65\x6b\x77\x5e\x3d\x3d\x55\xf8\x8b\x02\x2d\x9b\x8f\xa7\x11\x5a\x56\xfa\x8e\x70\x51\xd7\xb8\xe9\xeb\xbd\x4f\xe0\x48\xa9\xaa\xfe\xe5\xe8\x51\xfd\xa3\xd5\x38\x3a\x69\xbe\xb6\x11\xbb\x4c\xbd\xa0\x02\xca\x00\x3f\xfc\xef\x0f\xff\x17\x00\x00\xff\xff\x19\x9a\x50\xcb\xbb\xac\x00\x00")
+
+func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesEn_usAllJson,
+		"wski18n/resources/en_US.all.json",
+	)
+}
+
+func wski18nResourcesEn_usAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesEn_usAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 44219, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesEs_esAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesEs_esAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesEs_esAllJson,
+		"wski18n/resources/es_ES.all.json",
+	)
+}
+
+func wski18nResourcesEs_esAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesEs_esAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesFr_frAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8a\xe6\x52\x50\xa8\xe6\x52\x50\x50\x50\x50\xca\x4c\x51\xb2\x52\x50\x4a\xaa\x2c\x48\x2c\x2e\x56\x48\x4e\x2d\x2a\xc9\x4c\xcb\x4c\x4e\x2c\x49\x55\x48\xce\x48\x4d\xce\xce\xcc\x4b\x57\xd2\x81\x28\x2c\x29\x4a\xcc\x2b\xce\x49\x2c\xc9\xcc\xcf\x03\xe9\x08\xce\xcf\x4d\x55\x40\x12\x53\xc8\xcc\x53\x70\x2b\x4a\xcd\x4b\xce\x50\xe2\x52\x50\xa8\xe5\x8a\xe5\x02\x04\x00\x00\xff\xff\x45\xa4\xe9\x62\x65\x00\x00\x00")
+
+func wski18nResourcesFr_frAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesFr_frAllJson,
+		"wski18n/resources/fr_FR.all.json",
+	)
+}
+
+func wski18nResourcesFr_frAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesFr_frAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesIt_itAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesIt_itAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesIt_itAllJson,
+		"wski18n/resources/it_IT.all.json",
+	)
+}
+
+func wski18nResourcesIt_itAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesIt_itAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesJa_jaAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesJa_jaAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesJa_jaAllJson,
+		"wski18n/resources/ja_JA.all.json",
+	)
+}
+
+func wski18nResourcesJa_jaAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesJa_jaAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesKo_krAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesKo_krAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesKo_krAllJson,
+		"wski18n/resources/ko_KR.all.json",
+	)
+}
+
+func wski18nResourcesKo_krAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesKo_krAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesPt_brAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesPt_brAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesPt_brAllJson,
+		"wski18n/resources/pt_BR.all.json",
+	)
+}
+
+func wski18nResourcesPt_brAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesPt_brAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesZh_hansAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesZh_hansAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesZh_hansAllJson,
+		"wski18n/resources/zh_Hans.all.json",
+	)
+}
+
+func wski18nResourcesZh_hansAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesZh_hansAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _wski18nResourcesZh_hantAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
+
+func wski18nResourcesZh_hantAllJsonBytes() ([]byte, error) {
+	return bindataRead(
+		_wski18nResourcesZh_hantAllJson,
+		"wski18n/resources/zh_Hant.all.json",
+	)
+}
+
+func wski18nResourcesZh_hantAllJson() (*asset, error) {
+	bytes, err := wski18nResourcesZh_hantAllJsonBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1491513831, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+// Asset loads and returns the asset for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func Asset(name string) ([]byte, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
+		}
+		return a.bytes, nil
+	}
+	return nil, fmt.Errorf("Asset %s not found", name)
+}
+
+// MustAsset is like Asset but panics when Asset would return an error.
+// It simplifies safe initialization of global variables.
+func MustAsset(name string) []byte {
+	a, err := Asset(name)
+	if err != nil {
+		panic("asset: Asset(" + name + "): " + err.Error())
+	}
+
+	return a
+}
+
+// AssetInfo loads and returns the asset info for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func AssetInfo(name string) (os.FileInfo, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
+		}
+		return a.info, nil
+	}
+	return nil, fmt.Errorf("AssetInfo %s not found", name)
+}
+
+// AssetNames returns the names of the assets.
+func AssetNames() []string {
+	names := make([]string, 0, len(_bindata))
+	for name := range _bindata {
+		names = append(names, name)
+	}
+	return names
+}
+
+// _bindata is a table, holding each asset generator, mapped to its name.
+var _bindata = map[string]func() (*asset, error){
+	"wski18n/resources/.DS_Store": wski18nResourcesDs_store,
+	"wski18n/resources/de_DE.all.json": wski18nResourcesDe_deAllJson,
+	"wski18n/resources/en_US.all.json": wski18nResourcesEn_usAllJson,
+	"wski18n/resources/es_ES.all.json": wski18nResourcesEs_esAllJson,
+	"wski18n/resources/fr_FR.all.json": wski18nResourcesFr_frAllJson,
+	"wski18n/resources/it_IT.all.json": wski18nResourcesIt_itAllJson,
+	"wski18n/resources/ja_JA.all.json": wski18nResourcesJa_jaAllJson,
+	"wski18n/resources/ko_KR.all.json": wski18nResourcesKo_krAllJson,
+	"wski18n/resources/pt_BR.all.json": wski18nResourcesPt_brAllJson,
+	"wski18n/resources/zh_Hans.all.json": wski18nResourcesZh_hansAllJson,
+	"wski18n/resources/zh_Hant.all.json": wski18nResourcesZh_hantAllJson,
+}
+
+// AssetDir returns the file names below a certain
+// directory embedded in the file by go-bindata.
+// For example if you run go-bindata on data/... and data contains the
+// following hierarchy:
+//     data/
+//       foo.txt
+//       img/
+//         a.png
+//         b.png
+// then AssetDir("data") would return []string{"foo.txt", "img"}
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// AssetDir("") will return []string{"data"}.
+func AssetDir(name string) ([]string, error) {
+	node := _bintree
+	if len(name) != 0 {
+		cannonicalName := strings.Replace(name, "\\", "/", -1)
+		pathList := strings.Split(cannonicalName, "/")
+		for _, p := range pathList {
+			node = node.Children[p]
+			if node == nil {
+				return nil, fmt.Errorf("Asset %s not found", name)
+			}
+		}
+	}
+	if node.Func != nil {
+		return nil, fmt.Errorf("Asset %s not found", name)
+	}
+	rv := make([]string, 0, len(node.Children))
+	for childName := range node.Children {
+		rv = append(rv, childName)
+	}
+	return rv, nil
+}
+
+type bintree struct {
+	Func     func() (*asset, error)
+	Children map[string]*bintree
+}
+var _bintree = &bintree{nil, map[string]*bintree{
+	"wski18n": &bintree{nil, map[string]*bintree{
+		"resources": &bintree{nil, map[string]*bintree{
+			".DS_Store": &bintree{wski18nResourcesDs_store, map[string]*bintree{}},
+			"de_DE.all.json": &bintree{wski18nResourcesDe_deAllJson, map[string]*bintree{}},
+			"en_US.all.json": &bintree{wski18nResourcesEn_usAllJson, map[string]*bintree{}},
+			"es_ES.all.json": &bintree{wski18nResourcesEs_esAllJson, map[string]*bintree{}},
+			"fr_FR.all.json": &bintree{wski18nResourcesFr_frAllJson, map[string]*bintree{}},
+			"it_IT.all.json": &bintree{wski18nResourcesIt_itAllJson, map[string]*bintree{}},
+			"ja_JA.all.json": &bintree{wski18nResourcesJa_jaAllJson, map[string]*bintree{}},
+			"ko_KR.all.json": &bintree{wski18nResourcesKo_krAllJson, map[string]*bintree{}},
+			"pt_BR.all.json": &bintree{wski18nResourcesPt_brAllJson, map[string]*bintree{}},
+			"zh_Hans.all.json": &bintree{wski18nResourcesZh_hansAllJson, map[string]*bintree{}},
+			"zh_Hant.all.json": &bintree{wski18nResourcesZh_hantAllJson, map[string]*bintree{}},
+		}},
+	}},
+}}
+
+// RestoreAsset restores an asset under the given directory
+func RestoreAsset(dir, name string) error {
+	data, err := Asset(name)
+	if err != nil {
+		return err
+	}
+	info, err := AssetInfo(name)
+	if err != nil {
+		return err
+	}
+	err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
+	if err != nil {
+		return err
+	}
+	err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+	if err != nil {
+		return err
+	}
+	err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// RestoreAssets restores an asset under the given directory recursively
+func RestoreAssets(dir, name string) error {
+	children, err := AssetDir(name)
+	// File
+	if err != nil {
+		return RestoreAsset(dir, name)
+	}
+	// Dir
+	for _, child := range children {
+		err = RestoreAssets(dir, filepath.Join(name, child))
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func _filePath(dir, name string) string {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+}
+
diff --git a/wski18n/resources/de_DE.all.json b/wski18n/resources/de_DE.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/de_DE.all.json
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
new file mode 100644
index 0000000..2a0deb4
--- /dev/null
+++ b/wski18n/resources/en_US.all.json
@@ -0,0 +1,1446 @@
+[
+  {
+    "id": "Application exited unexpectedly",
+    "translation": "Application exited unexpectedly"
+  },
+  {
+    "id": "Run '{{.Name}} --help' for usage.\n",
+    "translation": "Run '{{.Name}} --help' for usage.\n"
+  },
+  {
+    "id": "error: ",
+    "translation": "error: "
+  },
+  {
+    "id": "not set",
+    "translation": "not set"
+  },
+  {
+    "id": "OpenWhisk cloud computing command line interface.",
+    "translation": "OpenWhisk cloud computing command line interface."
+  },
+  {
+    "id": "verbose output",
+    "translation": "verbose output"
+  },
+  {
+    "id": "debug level output",
+    "translation": "debug level output"
+  },
+  {
+    "id": "authorization `KEY`",
+    "translation": "authorization `KEY`"
+  },
+  {
+    "id": "whisk API `HOST`",
+    "translation": "whisk API `HOST`"
+  },
+  {
+    "id": "whisk API `VERSION`",
+    "translation": "whisk API `VERSION`"
+  },
+  {
+    "id": "bypass certificate checking",
+    "translation": "bypass certificate checking"
+  },
+  {
+    "id": "Unable to initialize server connection: {{.err}}",
+    "translation": "Unable to initialize server connection: {{.err}}"
+  },
+  {
+    "id": "Parameter arguments must be a key value pair: {{.args}}",
+    "translation": "Parameter arguments must be a key value pair: {{.args}}"
+  },
+  {
+    "id": "Annotation arguments must be a key value pair: {{.args}}",
+    "translation": "Annotation arguments must be a key value pair: {{.args}}"
+  },
+  {
+    "id": "Failed to parse arguments: {{.err}}",
+    "translation": "Failed to parse arguments: {{.err}}"
+  },
+  {
+    "id": "work with namespaces",
+    "translation": "work with namespaces"
+  },
+  {
+    "id": "list entities in the current namespace",
+    "translation": "list entities in the current namespace"
+  },
+  {
+    "id": "Unable to obtain the list of available namespaces: {{.err}}",
+    "translation": "Unable to obtain the list of available namespaces: {{.err}}"
+  },
+  {
+    "id": "get triggers, actions, and rules in the registry for a namespace",
+    "translation": "get triggers, actions, and rules in the registry for a namespace"
+  },
+  {
+    "id": "'{{.name}}' is not a valid qualified name: {{.err}}",
+    "translation": "'{{.name}}' is not a valid qualified name: {{.err}}"
+  },
+  {
+    "id": "Unable to obtain the list of entities for namespace '{{.namespace}}': {{.err}}",
+    "translation": "Unable to obtain the list of entities for namespace '{{.namespace}}': {{.err}}"
+  },
+  {
+    "id": "Entities in namespace: {{.namespace}}\n",
+    "translation": "Entities in namespace: {{.namespace}}\n"
+  },
+  {
+    "id": "list available namespaces",
+    "translation": "list available namespaces"
+  },
+  {
+    "id": "work with packages",
+    "translation": "work with packages"
+  },
+  {
+    "id": "bind parameters to a package",
+    "translation": "bind parameters to a package"
+  },
+  {
+    "id": "Invalid parameter argument '{{.param}}': {{.err}}",
+    "translation": "Invalid parameter argument '{{.param}}': {{.err}}"
+  },
+  {
+    "id": "Invalid annotation argument '{{.annotation}}': {{.err}}",
+    "translation": "Invalid annotation argument '{{.annotation}}': {{.err}}"
+  },
+  {
+    "id": "Binding creation failed: {{.err}}",
+    "translation": "Binding creation failed: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created binding {{.name}}\n",
+    "translation": "{{.ok}} created binding {{.name}}\n"
+  },
+  {
+    "id": "create a new package",
+    "translation": "create a new package"
+  },
+  {
+    "id": "Unable to create package '{{.name}}': {{.err}}",
+    "translation": "Unable to create package '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created package {{.name}}\n",
+    "translation": "{{.ok}} created package {{.name}}\n"
+  },
+  {
+    "id": "update an existing package, or create a package if it does not exist",
+    "translation": "update an existing package, or create a package if it does not exist"
+  },
+  {
+    "id": "Package update failed: {{.err}}",
+    "translation": "Package update failed: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} updated package {{.name}}\n",
+    "translation": "{{.ok}} updated package {{.name}}\n"
+  },
+  {
+    "id": "get package",
+    "translation": "get package"
+  },
+  {
+    "id": "Unable to get package '{{.name}}': {{.err}}",
+    "translation": "Unable to get package '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} got package {{.name}}\n",
+    "translation": "{{.ok}} got package {{.name}}\n"
+  },
+  {
+    "id": "delete package",
+    "translation": "delete package"
+  },
+  {
+    "id": "Unable to delete package '{{.name}}': {{.err}}",
+    "translation": "Unable to delete package '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} deleted package {{.name}}\n",
+    "translation": "{{.ok}} deleted package {{.name}}\n"
+  },
+  {
+    "id": "list all packages",
+    "translation": "list all packages"
+  },
+  {
+    "id": "No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\"",
+    "translation": "No valid namespace detected. Run 'wsk property set --namespace' or ensure the name argument is preceded by a \"/\""
+  },
+  {
+    "id": "Unable to obtain the list of packages for namespace '{{.name}}': {{.err}}",
+    "translation": "Unable to obtain the list of packages for namespace '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "refresh package bindings",
+    "translation": "refresh package bindings"
+  },
+  {
+    "id": "Package refresh for namespace '{{.name}}' failed: {{.err}}",
+    "translation": "Package refresh for namespace '{{.name}}' failed: {{.err}}"
+  },
+  {
+    "id": "{{.name}} refreshed successfully\n",
+    "translation": "{{.name}} refreshed successfully\n"
+  },
+  {
+    "id": "created bindings:",
+    "translation": "created bindings:"
+  },
+  {
+    "id": "updated bindings:",
+    "translation": "updated bindings:"
+  },
+  {
+    "id": "deleted bindings:",
+    "translation": "deleted bindings:"
+  },
+  {
+    "id": "The package refresh feature is not implemented in the target deployment",
+    "translation": "The package refresh feature is not implemented in the target deployment"
+  },
+  {
+    "id": "Package refresh for namespace '{{.name}}' failed due to unexpected HTTP status code: {{.code}}",
+    "translation": "Package refresh for namespace '{{.name}}' failed due to unexpected HTTP status code: {{.code}}"
+  },
+  {
+    "id": "annotation values in `KEY VALUE` format",
+    "translation": "annotation values in `KEY VALUE` format"
+  },
+  {
+    "id": "`FILE` containing annotation values in JSON format",
+    "translation": "`FILE` containing annotation values in JSON format"
+  },
+  {
+    "note-to-translators": "DO NOT TRANSLATE THE 'yes' AND 'no'.  THOSE ARE FIXED CLI ARGUMENT VALUES",
+    "id": "package visibility `SCOPE`; yes = shared, no = private",
+    "translation": "package visibility `SCOPE`; yes = shared, no = private"
+  },
+  {
+    "id": "summarize package details",
+    "translation": "summarize package details"
+  },
+  {
+    "id": "include publicly shared entities in the result",
+    "translation": "include publicly shared entities in the result"
+  },
+  {
+    "id": "exclude the first `SKIP` number of packages from the result",
+    "translation": "exclude the first `SKIP` number of packages from the result"
+  },
+  {
+    "id": "only return `LIMIT` number of packages from the collection",
+    "translation": "only return `LIMIT` number of packages from the collection"
+  },
+  {
+    "id": "property",
+    "translation": "property"
+  },
+  {
+    "id": "work with whisk properties",
+    "translation": "work with whisk properties"
+  },
+  {
+    "id": "set property",
+    "translation": "set property"
+  },
+  {
+    "id": "Unable to set the property value: {{.err}}",
+    "translation": "Unable to set the property value: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} whisk auth set to {{.auth}}\n",
+    "translation": "{{.ok}} whisk auth set to {{.auth}}\n"
+  },
+  {
+    "id": "Unable to set API host value; the API host value '{{.apihost}}' is invalid: {{.err}}",
+    "translation": "Unable to set API host value; the API host value '{{.apihost}}' is invalid: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} whisk API host set to {{.host}}\n",
+    "translation": "{{.ok}} whisk API host set to {{.host}}\n"
+  },
+  {
+    "id": "{{.ok}} whisk API version set to {{.version}}\n",
+    "translation": "{{.ok}} whisk API version set to {{.version}}\n"
+  },
+  {
+    "id": "Authenticated user does not have namespace '{{.name}}'; set command failed: {{.err}}",
+    "translation": "Authenticated user does not have namespace '{{.name}}'; set command failed: {{.err}}"
+  },
+  {
+    "id": "Namespace '{{.name}}' is not in the list of entitled namespaces",
+    "translation": "Namespace '{{.name}}' is not in the list of entitled namespaces"
+  },
+  {
+    "id": "{{.ok}} whisk namespace set to {{.name}}\n",
+    "translation": "{{.ok}} whisk namespace set to {{.name}}\n"
+  },
+  {
+    "id": "Unable to set the property value(s): {{.err}}",
+    "translation": "Unable to set the property value(s): {{.err}}"
+  },
+  {
+    "id": "unset property",
+    "translation": "unset property"
+  },
+  {
+    "id": "Unable to unset the property value: {{.err}}",
+    "translation": "Unable to unset the property value: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} whisk auth unset",
+    "translation": "{{.ok}} whisk auth unset"
+  },
+  {
+    "id": "{{.ok}} whisk namespace unset",
+    "translation": "{{.ok}} whisk namespace unset"
+  },
+  {
+    "id": "{{.ok}} whisk API host unset",
+    "translation": "{{.ok}} whisk API host unset"
+  },
+  {
+    "id": "{{.ok}} whisk API version unset",
+    "translation": "{{.ok}} whisk API version unset"
+  },
+  {
+    "id": "; the default value of {{.default}} will be used.\n",
+    "translation": "; the default value of {{.default}} will be used.\n"
+  },
+  {
+    "id": "; there is no default value that can be used.\n",
+    "translation": "; there is no default value that can be used.\n"
+  },
+  {
+    "id": "get property",
+    "translation": "get property"
+  },
+  {
+    "id": "whisk auth",
+    "translation": "whisk auth"
+  },
+  {
+    "id": "whisk API host",
+    "translation": "whisk API host"
+  },
+  {
+    "id": "whisk API version",
+    "translation": "whisk API version"
+  },
+  {
+    "id": "whisk namespace",
+    "translation": "whisk namespace"
+  },
+  {
+    "id": "whisk CLI version",
+    "translation": "whisk CLI version"
+  },
+  {
+    "id": "Unknown",
+    "translation": "Unknown"
+  },
+  {
+    "id": "whisk API build",
+    "translation": "whisk API build"
+  },
+  {
+    "id": "whisk API build number",
+    "translation": "whisk API build number"
+  },
+  {
+    "id": "Unable to obtain API build information: {{.err}}",
+    "translation": "Unable to obtain API build information: {{.err}}"
+  },
+  {
+    "id": "authorization key",
+    "translation": "authorization key"
+  },
+  {
+    "id": "whisk API build version",
+    "translation": "whisk API build version"
+  },
+  {
+    "id": "all properties",
+    "translation": "all properties"
+  },
+  {
+    "id": "whisk `NAMESPACE`",
+    "translation": "whisk `NAMESPACE`"
+  },
+  {
+    "id": "Unable to locate properties file '{{.filename}}': {{.err}}",
+    "translation": "Unable to locate properties file '{{.filename}}': {{.err}}"
+  },
+  {
+    "id": "Unable to read the properties file '{{.filename}}': {{.err}}",
+    "translation": "Unable to read the properties file '{{.filename}}': {{.err}}"
+  },
+  {
+    "id": "Invalid host address '{{.host}}': {{.err}}",
+    "translation": "Invalid host address '{{.host}}': {{.err}}"
+  },
+  {
+    "id": "Whisk properties file write failure: {{.err}}",
+    "translation": "Whisk properties file write failure: {{.err}}"
+  },
+  {
+    "id": "work with rules",
+    "translation": "work with rules"
+  },
+  {
+    "id": "enable rule",
+    "translation": "enable rule"
+  },
+  {
+    "id": "Unable to enable rule '{{.name}}': {{.err}}",
+    "translation": "Unable to enable rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} enabled rule {{.name}}\n",
+    "translation": "{{.ok}} enabled rule {{.name}}\n"
+  },
+  {
+    "id": "disable rule",
+    "translation": "disable rule"
+  },
+  {
+    "id": "Unable to disable rule '{{.name}}': {{.err}}",
+    "translation": "Unable to disable rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} disabled rule {{.name}}\n",
+    "translation": "{{.ok}} disabled rule {{.name}}\n"
+  },
+  {
+    "id": "get rule status",
+    "translation": "get rule status"
+  },
+  {
+    "id": "Unable to get rule '{{.name}}': {{.err}}",
+    "translation": "Unable to get rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to get status of rule '{{.name}}': {{.err}}",
+    "translation": "Unable to get status of rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} rule {{.name}} is {{.status}}\n",
+    "translation": "{{.ok}} rule {{.name}} is {{.status}}\n"
+  },
+  {
+    "id": "create new rule",
+    "translation": "create new rule"
+  },
+  {
+    "id": "Unable to create rule '{{.name}}': {{.err}}",
+    "translation": "Unable to create rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created rule {{.name}}\n",
+    "translation": "{{.ok}} created rule {{.name}}\n"
+  },
+  {
+    "id": "update an existing rule, or create a rule if it does not exist",
+    "translation": "update an existing rule, or create a rule if it does not exist"
+  },
+  {
+    "id": "Unable to update rule '{{.name}}': {{.err}}",
+    "translation": "Unable to update rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} updated rule {{.name}}\n",
+    "translation": "{{.ok}} updated rule {{.name}}\n"
+  },
+  {
+    "id": "get rule",
+    "translation": "get rule"
+  },
+  {
+    "id": "Unable to retrieve rule '{{.name}}': {{.err}}",
+    "translation": "Unable to retrieve rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} got rule {{.name}}\n",
+    "translation": "{{.ok}} got rule {{.name}}\n"
+  },
+  {
+    "id": "delete rule",
+    "translation": "delete rule"
+  },
+  {
+    "id": "Unable to delete rule '{{.name}}': {{.err}}",
+    "translation": "Unable to delete rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} deleted rule {{.name}}\n",
+    "translation": "{{.ok}} deleted rule {{.name}}\n"
+  },
+  {
+    "id": "list all rules",
+    "translation": "list all rules"
+  },
+  {
+    "id": "Namespace '{{.name}}' is invalid: {{.err}}\n",
+    "translation": "Namespace '{{.name}}' is invalid: {{.err}}\n"
+  },
+  {
+    "id": "Unable to obtain the list of rules for namespace '{{.name}}': {{.err}}",
+    "translation": "Unable to obtain the list of rules for namespace '{{.name}}': {{.err}}"
+  },
+  {
+    "note-to-translators": "DO NOT TRANSLATE THE 'yes' AND 'no'.  THOSE ARE FIXED CLI ARGUMENT VALUES",
+    "id": "rule visibility `SCOPE`; yes = shared, no = private",
+    "translation": "rule visibility `SCOPE`; yes = shared, no = private"
+  },
+  {
+    "id": "automatically enable rule after creating it",
+    "translation": "automatically enable rule after creating it"
+  },
+  {
+    "id": "automatically disable rule before deleting it",
+    "translation": "automatically disable rule before deleting it"
+  },
+  {
+    "id": "summarize rule details",
+    "translation": "summarize rule details"
+  },
+  {
+    "id": "work with the sdk",
+    "translation": "work with the sdk"
+  },
+  {
+    "id": "install SDK artifacts",
+    "translation": "install SDK artifacts"
+  },
+  {
+    "id": "install SDK artifacts, where valid COMPONENT values are docker, ios, and bashauto",
+    "translation": "install SDK artifacts, where valid COMPONENT values are docker, iOS, and bashauto"
+  },
+  {
+    "id": "The SDK component argument is missing. One component (docker, ios, or bashauto) must be specified",
+    "translation": "The SDK component argument is missing. One component (docker, ios, or bashauto) must be specified"
+  },
+  {
+    "id": "Unable to generate '{{.name}}': {{.err}}",
+    "translation": "Unable to generate '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "bash_completion_msg",
+    "translation": "The bash auto-completion script ({{.name}}) is installed in the current directory.\nTo enable command line completion of wsk commands, source the auto completion script into your bash environment\n"
+  },
+  {
+    "id": "The SDK component argument '{{.component}}' is invalid. Valid components are docker, ios and bashauto",
+    "translation": "The SDK component argument '{{.component}}' is invalid. Valid components are docker, ios and bashauto"
+  },
+  {
+    "id": "The file {{.name}} already exists.  Delete it and retry.",
+    "translation": "The file {{.name}} already exists.  Delete it and retry."
+  },
+  {
+    "id": "The {{.component}} SDK installation failed: {{.err}}",
+    "translation": "The {{.component}} SDK installation failed: {{.err}}"
+  },
+  {
+    "id": "The docker skeleton is now installed at the current directory.",
+    "translation": "The docker skeleton is now installed at the current directory."
+  },
+  {
+    "id": "Downloaded OpenWhisk iOS starter app. Unzip {{.name}} and open the project in Xcode.\n",
+    "translation": "Downloaded OpenWhisk iOS starter app. Unzip {{.name}} and open the project in Xcode.\n"
+  },
+  {
+    "id": "Unable to retrieve '{{.urlpath}}' SDK: {{.err}}",
+    "translation": "Unable to retrieve '{{.urlpath}}' SDK: {{.err}}"
+  },
+  {
+    "id": "Server failed to send the '{{.component}}' SDK: {{.err}}",
+    "translation": "Server failed to send the '{{.component}}' SDK: {{.err}}"
+  },
+  {
+    "id": "Error creating SDK file {{.name}}: {{.err}}",
+    "translation": "Error creating SDK file {{.name}}: {{.err}}"
+  },
+  {
+    "id": "Error copying server response into file: {{.err}}",
+    "translation": "Error copying server response into file: {{.err}}"
+  },
+  {
+    "id": "The directory {{.name}} already exists.  Delete it and retry.",
+    "translation": "The directory {{.name}} already exists.  Delete it and retry."
+  },
+  {
+    "id": "Error unGzipping file {{.name}}: {{.err}}",
+    "translation": "Error unGzipping file {{.name}}: {{.err}}"
+  },
+  {
+    "id": "Error untarring file {{.name}}: {{.err}}",
+    "translation": "Error untarring file {{.name}}: {{.err}}"
+  },
+  {
+    "id": "work with triggers",
+    "translation": "work with triggers"
+  },
+  {
+    "id": "fire trigger event",
+    "translation": "fire trigger event"
+  },
+  {
+    "id": "Unable to fire trigger '{{.name}}': {{.err}}",
+    "translation": "Unable to fire trigger '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} triggered /{{.namespace}}/{{.name}} with id {{.id}}\n",
+    "translation": "{{.ok}} triggered /{{.namespace}}/{{.name}} with id {{.id}}\n"
+  },
+  {
+    "id": "create new trigger",
+    "translation": "create new trigger"
+  },
+  {
+    "note-to-translators": "DO NOT TRANSLATE THE 'yes' AND 'no'.  THOSE ARE FIXED CLI ARGUMENT VALUES",
+    "id": "Invalid --shared argument value '{{.argval}}'; valid values are 'yes' or 'no'",
+    "translation": "Invalid --shared argument value '{{.argval}}'; valid values are 'yes' or 'no'"
+  },
+  {
+    "id": "Unable to create trigger '{{.name}}': {{.err}}",
+    "translation": "Unable to create trigger '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created trigger {{.name}}\n",
+    "translation": "{{.ok}} created trigger {{.name}}\n"
+  },
+  {
+    "id": "update an existing trigger, or create a trigger if it does not exist",
+    "translation": "update an existing an trigger, or create a trigger if it does not exist"
+  },
+  {
+    "id": "Unable to update trigger '{{.name}}': {{.err}}",
+    "translation": "Unable to update trigger '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} updated trigger {{.name}}\n",
+    "translation": "{{.ok}} updated trigger {{.name}}\n"
+  },
+  {
+    "id": "get trigger",
+    "translation": "get trigger"
+  },
+  {
+    "id": "Unable to get trigger '{{.name}}': {{.err}}",
+    "translation": "Unable to get trigger '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} got trigger {{.name}}\n",
+    "translation": "{{.ok}} got trigger {{.name}}\n"
+  },
+  {
+    "id": "delete trigger",
+    "translation": "delete trigger"
+  },
+  {
+    "id": "Unable to delete trigger '{{.name}}': {{.err}}",
+    "translation": "Unable to delete trigger '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} deleted trigger {{.name}}\n",
+    "translation": "{{.ok}} deleted trigger {{.name}}\n"
+  },
+  {
+    "id": "list all triggers",
+    "translation": "list all triggers"
+  },
+  {
+    "id": "Unable to obtain the list of triggers for namespace '{{.name}}': {{.err}}",
+    "translation": "Unable to obtain the list of triggers for namespace '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to invoke trigger '{{.trigname}}' feed action '{{.feedname}}'; feed is not configured: {{.err}}",
+    "translation": "Unable to invoke trigger '{{.trigname}}' feed action '{{.feedname}}'; feed is not configured: {{.err}}"
+  },
+  {
+    "note-to-translators": "DO NOT TRANSLATE THE 'yes' AND 'no'.  THOSE ARE FIXED CLI ARGUMENT VALUES",
+    "id": "trigger visibility `SCOPE`; yes = shared, no = private",
+    "translation": "trigger visibility `SCOPE`; yes = shared, no = private"
+  },
+  {
+    "id": "trigger feed `ACTION_NAME`",
+    "translation": "trigger feed `ACTION_NAME`"
+  },
+  {
+    "id": "summarize trigger details",
+    "translation": "summarize trigger details"
+  },
+  {
+    "id": "parameter values in `KEY VALUE` format",
+    "translation": "parameter values in `KEY VALUE` format"
+  },
+  {
+    "id": "`FILE` containing parameter values in JSON format",
+    "translation": "`FILE` containing parameter values in JSON format"
+  },
+  {
+    "id": "Arguments must be comma separated, and must be quoted if they contain spaces.",
+    "translation": "Arguments must be comma separated, and must be quoted if they contain spaces."
+  },
+  {
+    "id": "Invalid arguments: {{.err}}",
+    "translation": "Invalid arguments: {{.err}}"
+  },
+  {
+    "id": "The argument `{{.arg}}` is invalid: {{.err}}",
+    "translation": "The argument `{{.arg}}` is invalid: {{.err}}"
+  },
+  {
+    "id": "The argument `{{.arg}}` is invalid JSON: {{.err}}",
+    "translation": "The argument `{{.arg}}` is invalid JSON: {{.err}}"
+  },
+  {
+    "id": "private",
+    "translation": "private"
+  },
+  {
+    "id": "shared",
+    "translation": "shared"
+  },
+  {
+    "id": "The file '{{.name}}' does not exist.",
+    "translation": "The file '{{.name}}' does not exist."
+  },
+  {
+    "id": "Error creating unGzip file '{{.name}}': {{.err}}",
+    "translation": "Error creating unGzip file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Error opening Gzip file '{{.name}}': {{.err}}",
+    "translation": "Error opening Gzip file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to unzip file '{{.name}}': {{.err}}",
+    "translation": "Unable to unzip file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to opens '{{.name}}' for unzipping: {{.err}}",
+    "translation": "Unable to opens '{{.name}}' for unzipping: {{.err}}"
+  },
+  {
+    "id": "Unable to create directory '{{.dir}}' while unzipping '{{.name}}': {{.err}}",
+    "translation": "Unable to create directory '{{.dir}}' while unzipping '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to open zipped file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
+    "translation": "Unable to open zipped file '{{.file}}' while unzipping '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to create file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
+    "translation": "Unable to create file '{{.file}}' while unzipping '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Error opening tar file '{{.name}}': {{.err}}",
+    "translation": "Error opening tar file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Error reading tar file '{{.name}}': {{.err}}",
+    "translation": "Error reading tar file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to create directory '{{.dir}}' while untarring '{{.name}}': {{.err}}",
+    "translation": "Unable to create directory '{{.dir}}' while untarring '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to create file '{{.file}}' while untarring '{{.name}}': {{.err}}",
+    "translation": "Unable to create file '{{.file}}' while untarring '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to untar file '{{.name}}': {{.err}}",
+    "translation": "Unable to untar file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to untar '{{.name}}' due to unexpected tar file type\n",
+    "translation": "Unable to untar '{{.name}}' due to unexpected tar file type\n"
+  },
+  {
+    "id": "work with actions",
+    "translation": "work with actions"
+  },
+  {
+    "id": "create a new action",
+    "translation": "create a new action"
+  },
+  {
+    "id": "Unable to parse action command arguments: {{.err}}",
+    "translation": "Unable to parse action command arguments: {{.err}}"
+  },
+  {
+    "id": "Unable to create action '{{.name}}': {{.err}}",
+    "translation": "Unable to create action '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created action {{.name}}\n",
+    "translation": "{{.ok}} created action {{.name}}\n"
+  },
+  {
+    "id": "update an existing action, or create an action if it does not exist",
+    "translation": "update an existing action, or create an action if it does not exist"
+  },
+  {
+    "id": "Unable to update action: {{.err}}",
+    "translation": "Unable to update action: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} updated action {{.name}}\n",
+    "translation": "{{.ok}} updated action {{.name}}\n"
+  },
+  {
+    "id": "invoke action",
+    "translation": "invoke action"
+  },
+  {
+    "id": "Unable to invoke action '{{.name}}': {{.err}}",
+    "translation": "Unable to invoke action '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} invoked /{{.namespace}}/{{.name}} with id {{.id}}\n",
+    "translation": "{{.ok}} invoked /{{.namespace}}/{{.name}} with id {{.id}}\n"
+  },
+  {
+    "id": "get action",
+    "translation": "get action"
+  },
+  {
+    "id": "Unable to get action: {{.err}}",
+    "translation": "Unable to get action: {{.err}}"
+  },
+  {
+    "id": "action",
+    "translation": "action"
+  },
+  {
+    "id": "{{.ok}} got action {{.name}}\n",
+    "translation": "{{.ok}} got action {{.name}}\n"
+  },
+  {
+    "id": "delete action",
+    "translation": "delete action"
+  },
+  {
+    "id": "Unable to delete action '{{.name}}': {{.err}}",
+    "translation": "Unable to delete action '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "{{.ok}} deleted action {{.name}}\n",
+    "translation": "{{.ok}} deleted action {{.name}}\n"
+  },
+  {
+    "id": "list all actions",
+    "translation": "list all actions"
+  },
+  {
+    "id": "Unable to obtain the list of actions for namespace '{{.name}}': {{.err}}",
+    "translation": "Unable to obtain the list of actions for namespace '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Could not find 'main' method in '{{.name}}'",
+    "translation": "Could not find 'main' method in '{{.name}}'"
+  },
+  {
+    "id": "Unable to get action '{{.name}}': {{.err}}",
+    "translation": "Unable to get action '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "File '{{.name}}' is not a valid file or it does not exist: {{.err}}",
+    "translation": "File '{{.name}}' is not a valid file or it does not exist: {{.err}}"
+  },
+  {
+    "id": "Unable to read '{{.name}}': {{.err}}",
+    "translation": "Unable to read '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "'{{.name}}' is not a supported action runtime",
+    "translation": "'{{.name}}' is not a supported action runtime"
+  },
+  {
+    "id": "creating an action from a .zip artifact requires specifying the action kind explicitly",
+    "translation": "creating an action from a .zip artifact requires specifying the action kind explicitly"
+  },
+  {
+    "id": "Java actions require --main to specify the fully-qualified name of the main class",
+    "translation": "Java actions require --main to specify the fully-qualified name of the main class"
+  },
+  {
+    "id": "treat ACTION as docker image path on dockerhub",
+    "translation": "treat ACTION as docker image path on dockerhub"
+  },
+  {
+    "id": "treat ACTION as the name of an existing action",
+    "translation": "treat ACTION as the name of an existing action"
+  },
+  {
+    "id": "treat ACTION as comma separated sequence of actions to invoke",
+    "translation": "treat ACTION as comma separated sequence of actions to invoke"
+  },
+  {
+    "id": "the `KIND` of the action runtime (example: swift:default, nodejs:default)",
+    "translation": "the `KIND` of the action runtime (example: swift:default, nodejs:default)"
+  },
+  {
+    "id": "the name of the action entry point (function or fully-qualified method name when applicable)",
+    "translation": "the name of the action entry point (function or fully-qualified method name when applicable)"
+  },
+  {
+    "id": "action visibility `SCOPE`; yes = shared, no = private",
+    "translation": "action visibility `SCOPE`; yes = shared, no = private"
+  },
+  {
+    "id": "the timeout `LIMIT` in milliseconds after which the action is terminated",
+    "translation": "the timeout `LIMIT` in milliseconds after which the action is terminated"
+  },
+  {
+    "id": "the maximum memory `LIMIT` in MB for the action",
+    "translation": "the maximum memory `LIMIT` in MB for the action"
+  },
+  {
+    "id": "the maximum log size `LIMIT` in MB for the action",
+    "translation": "the maximum log size `LIMIT` in MB for the action"
+  },
+  {
+    "id": "blocking invoke",
+    "translation": "blocking invoke"
+  },
+  {
+    "id": "blocking invoke; show only activation result (unless there is a failure)",
+    "translation": "blocking invoke; show only activation result (unless there is a failure)"
+  },
+  {
+    "id": "exclude the first `SKIP` number of actions from the result",
+    "translation": "exclude the first `SKIP` number of actions from the result"
+  },
+  {
+    "id": "only return `LIMIT` number of actions from the collection",
+    "translation": "only return `LIMIT` number of actions from the collection"
+  },
+  {
+    "id": "summarize action details",
+    "translation": "summarize action details"
+  },
+  {
+    "id": "work with activations",
+    "translation": "work with activations"
+  },
+  {
+    "id": "list activations",
+    "translation": "list activations"
+  },
+  {
+    "id": "Namespace '{{.name}}' is invalid",
+    "translation": "Namespace '{{.name}}' is invalid"
+  },
+  {
+    "id": "Unable to obtain the list of activations for namespace '{{.name}}': {{.err}}",
+    "translation": "Unable to obtain the list of activations for namespace '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "get activation",
+    "translation": "get activation"
+  },
+  {
+    "id": "Unable to get activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get activation '{{.id}}': {{.err}}"
+  },
+  {
+    "id": "activation result for /{{.namespace}}/{{.name}} ({{.status}} at {{.time}})\n",
+    "translation": "activation result for /{{.namespace}}/{{.name}} ({{.status}} at {{.time}})\n"
+  },
+  {
+    "id": "{{.ok}} got activation {{.id}}\n",
+    "translation": "{{.ok}} got activation {{.id}}\n"
+  },
+  {
+    "id": "get the logs of an activation",
+    "translation": "get the logs of an activation"
+  },
+  {
+    "id": "Unable to get logs for activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get logs for activation '{{.id}}': {{.err}}"
+  },
+  {
+    "id": "Unable to get result for activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get result for activation '{{.id}}': {{.err}}"
+  },
+  {
+    "id": "poll continuously for log messages from currently running actions",
+    "translation": "poll continuously for log messages from currently running actions"
+  },
+  {
+    "id": "Poll terminated",
+    "translation": "Poll terminated"
+  },
+  {
+    "id": "Enter Ctrl-c to exit.",
+    "translation": "Enter Ctrl-c to exit."
+  },
+  {
+    "id": "Polling for activation logs\n",
+    "translation": "Polling for activation logs\n"
+  },
+  {
+    "id": "\nActivation: {{.name}} ({{.id}})\n",
+    "translation": "\nActivation: {{.name}} ({{.id}})\n"
+  },
+  {
+    "id": "exclude the first `SKIP` number of activations from the result",
+    "translation": "exclude the first `SKIP` number of activations from the result"
+  },
+  {
+    "id": "only return `LIMIT` number of activations from the collection",
+    "translation": "only return `LIMIT` number of activations from the collection"
+  },
+  {
+    "id": "include full activation description",
+    "translation": "include full activation description"
+  },
+  {
+    "id": "return activations with timestamps earlier than `UPTO`; measured in milliseconds since Th, 01, Jan 1970",
+    "translation": "return activations with timestamps earlier than `UPTO`; measured in milliseconds since Th, 01, Jan 1970"
+  },
+  {
+    "id": "return activations with timestamps later than `SINCE`; measured in milliseconds since Th, 01, Jan 1970",
+    "translation": "return activations with timestamps later than `SINCE`; measured in milliseconds since Th, 01, Jan 1970"
+  },
+  {
+    "id": "summarize activation details",
+    "translation": "summarize activation details"
+  },
+  {
+    "id": "stop polling after `SECONDS` seconds",
+    "translation": "stop polling after `SECONDS` seconds"
+  },
+  {
+    "id": "start polling for activations `SECONDS` seconds ago",
+    "translation": "start polling for activations `SECONDS` seconds ago"
+  },
+  {
+    "id": "start polling for activations `MINUTES` minutes ago",
+    "translation": "start polling for activations `MINUTES` minutes ago"
+  },
+  {
+    "id": "start polling for activations `HOURS` hours ago",
+    "translation": "start polling for activations `HOURS` hours ago"
+  },
+  {
+    "id": "start polling for activations `DAYS` days ago",
+    "translation": "start polling for activations `DAYS` days ago"
+  },
+  {
+    "id": "Arguments for '{{.arg}}' must be a key/value pair",
+    "translation": "Arguments for '{{.arg}}' must be a key/value pair"
+  },
+  {
+    "id": "The parameter arguments are invalid: {{.err}}",
+    "translation": "The parameter arguments are invalid: {{.err}}"
+  },
+  {
+    "id": "The annotation arguments are invalid: {{.err}}",
+    "translation": "The annotation arguments are invalid: {{.err}}"
+  },
+  {
+    "id": "An action name and action are required.",
+    "translation": "An action name and action are required."
+  },
+  {
+    "id": "An action name is required.",
+    "translation": "An action name is required."
+  },
+  {
+    "id": "An action name is required. An action is optional.",
+    "translation": "An action name is required. An action is optional."
+  },
+  {
+    "id": "An activation ID is required.",
+    "translation": "An activation ID is required."
+  },
+  {
+    "id": "A package name and binding name are required.",
+    "translation": "A package name and binding name are required."
+  },
+  {
+    "id": "A package name is required.",
+    "translation": "A package name is required."
+  },
+  {
+    "id": "A rule name is required.",
+    "translation": "A rule name is required."
+  },
+  {
+    "id": "A rule, trigger and action name are required.",
+    "translation": "A rule, trigger and action name are required."
+  },
+  {
+    "id": "A trigger name is required.",
+    "translation": "A trigger name is required."
+  },
+  {
+    "id": "A trigger name is required. A payload is optional.",
+    "translation": "A trigger name is required. A payload is optional."
+  },
+  {
+    "id": "An optional namespace is the only valid argument.",
+    "translation": "An optional namespace is the only valid argument."
+  },
+  {
+    "id": "Invalid argument(s). {{.required}}",
+    "translation": "Invalid argument(s). {{.required}}"
+  },
+  {
+    "id": "Invalid argument(s): {{.args}}. {{.required}}",
+    "translation": "Invalid argument(s): {{.args}}. {{.required}}"
+  },
+  {
+    "id": "exactly",
+    "translation": "exactly"
+  },
+  {
+    "id": "at least",
+    "translation": "at least"
+  },
+  {
+    "id": "no more than",
+    "translation": "no more than"
+  },
+  {
+    "id": "No arguments are required.",
+    "translation": "No arguments are required."
+  },
+  {
+    "id": "status",
+    "translation": "status"
+  },
+  {
+    "id": "parameters",
+    "translation": "parameters"
+  },
+  {
+    "id": "default",
+    "translation": "default"
+  },
+  {
+    "id": "An argument must be provided for '{{.arg}}'",
+    "translation": "An argument must be provided for '{{.arg}}'"
+  },
+  {
+    "id": "The API host is not valid: {{.err}}",
+    "translation": "The API host is not valid: {{.err}}"
+  },
+  {
+    "id": "An API host must be provided.",
+    "translation": "An API host must be provided."
+  },
+  {
+    "id": "Invalid field filter '{{.arg}}'.",
+    "translation": "Invalid field filter '{{.arg}}'."
+  },
+  {
+    "id": "{{.ok}} got activation {{.id}}, displaying field {{.field}}\n",
+    "translation": "{{.ok}} got activation {{.id}}, displaying field {{.field}}\n"
+  },
+  {
+    "id": "{{.ok}} got action {{.name}}, displaying field {{.field}}\n",
+    "translation": "{{.ok}} got action {{.name}}, displaying field {{.field}}\n"
+  },
+  {
+    "id": "{{.ok}} got package {{.name}}, displaying field {{.field}}\n",
+    "translation": "{{.ok}} got package {{.name}}, displaying field {{.field}}\n"
+  },
+  {
+    "id": "{{.ok}} got rule {{.name}}, displaying field {{.field}}\n",
+    "translation": "{{.ok}} got rule {{.name}}, displaying field {{.field}}\n"
+  },
+  {
+    "id": "{{.ok}} got trigger {{.name}}, displaying field {{.field}}\n",
+    "translation": "{{.ok}} got trigger {{.name}}, displaying field {{.field}}\n"
+  },
+  {
+    "id": "An API path, an API verb, and an action name are required.",
+    "translation": "An API path, an API verb, and an action name are required."
+  },
+  {
+    "id": "An API path and an API verb are required.",
+    "translation": "An API path and an API verb are required."
+  },
+  {
+    "id":"'{{.name}}' is not a valid action name: {{.err}}",
+    "translation": "'{{.name}}' is not a valid action name: {{.err}}"
+  },
+  {
+    "id":"'{{.name}}' is not a valid action name.",
+    "translation": "'{{.name}}' is not a valid action name."
+  },
+  {
+    "id": "Unable to create API: {{.err}}",
+    "translation": "Unable to create API: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+    "translation": "{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n"
+  },
+  {
+    "id": "Unable to parse api command arguments: {{.err}}",
+    "translation": "Unable to parse api command arguments: {{.err}}"
+  },
+  {
+    "id": "create a new API",
+    "translation": "create a new API"
+  },
+  {
+    "id": "update an existing API",
+    "translation": "update an existing API"
+  },
+  {
+    "id": "Unable to update API: {{.err}}",
+    "translation": "Unable to update API: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} updated API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+    "translation": "{{.ok}} updated API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n"
+  },
+  {
+    "id": "get API",
+    "translation": "get API"
+  },
+  {
+    "id": "Unable to get API '{{.name}}': {{.err}}",
+    "translation": "Unable to get API '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "delete an API",
+    "translation": "delete an API"
+  },
+  {
+    "id": "Unable to delete API: {{.err}}",
+    "translation": "Unable to delete API: {{.err}}"
+  },
+  {
+    "id": "{{.ok}} deleted API {{.basepath}}\n",
+    "translation": "{{.ok}} deleted API {{.basepath}}\n"
+  },
+  {
+    "id": "{{.ok}} deleted {{.path}} from {{.basepath}}\n",
+    "translation": "{{.ok}} deleted {{.path}} from {{.basepath}}\n"
+  },
+  {
+    "id": "{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
+    "translation": "{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n"
+  },
+  {
+    "id": "list APIs",
+    "translation": "list APIs"
+  },
+  {
+    "id": "Unable to obtain the API list: {{.err}}",
+    "translation": "Unable to obtain the API list: {{.err}}"
+  },
+  {
+    "id": "'{{.verb}}' is not a valid API verb.  Valid values are: {{.verbs}}",
+    "translation": "'{{.verb}}' is not a valid API verb.  Valid values are: {{.verbs}}"
+  },
+  {
+    "id": "`ACTION` to invoke when API is called",
+    "translation": "`ACTION` to invoke when API is called"
+  },
+  {
+    "id": "relative `API_PATH` of API",
+    "translation": "relative `API_PATH` of API"
+  },
+  {
+    "id": "API `API_VERB`",
+    "translation": "API `API_VERB`"
+  },
+  {
+    "id": "API collection `NAME` (default NAMESPACE)",
+    "translation": "API collection `NAME` (default NAMESPACE)"
+  },
+  {
+    "id": "The API `BASE_PATH` to which the API_PATH is relative",
+    "translation": "The API `BASE_PATH` to which the API_PATH is relative"
+  },
+  {
+    "id": "{{.ok}} APIs\n",
+    "translation": "{{.ok}} APIs\n"
+  },
+  {
+    "id": "{{.url}} {{.operation}} {{.action}}\n",
+    "translation": "{{.url}} {{.operation}} {{.action}}\n"
+  },
+  {
+    "id": "An API base path is required.  An optional API relative path and operation may also be provided.",
+    "translation": "An API base path is required.  An optional API relative path and operation may also be provided."
+  },
+  {
+    "id": "'{{.path}}' must begin with '/'.",
+    "translation": "'{{.path}}' must begin with '/'."
+  },
+  {
+    "id": "Unable to parse swagger file: {{.err}}",
+    "translation": "Unable to parse swagger file: {{.err}}"
+  },
+  {
+    "id": "Error reading swagger file '{{.name}}': {{.err}}",
+    "translation": "Error reading swagger file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "A configuration file was not specified.",
+    "translation": "A configuration file was not specified."
+  },
+  {
+    "id": "Error parsing swagger file '{{.name}}': {{.err}}",
+    "translation": "Error parsing swagger file '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Swagger file is invalid (missing basePath, info, paths, or swagger fields)",
+    "translation": "Swagger file is invalid (missing basePath, info, paths, or swagger fields)"
+  },
+  {
+    "id": "Swagger file basePath must start with a leading slash (/)",
+    "translation": "Swagger file basePath must start with a leading slash (/)"
+  },
+  {
+    "id": "API does not exist for basepath {{.basepath}}",
+    "translation": "API does not exist for basepath {{.basepath}}"
+  },
+  {
+    "id": "API does not exist for API name {{.apiname}}",
+    "translation": "API does not exist for API name {{.apiname}}"
+  },
+  {
+    "id": "An API name can only be specified once",
+    "translation": "An API name can only be specified once"
+  },
+  {
+    "id": "Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.",
+    "translation": "Specify a swagger file or specify an API base path with an API path, an API verb, and an action name."
+  },
+  {
+    "id": "Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.",
+    "translation": "Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name."
+  },
+  {
+    "id": "Cannot use value '{{.arg}}' for shared.",
+    "translation": "Cannot use value '{{.arg}}' for shared."
+  },
+  {
+    "id": "Action",
+    "translation": "Action"
+  },
+  {
+    "id": "Verb",
+    "translation": "Verb"
+  },
+  {
+    "id": "API Name",
+    "translation": "API Name"
+  },
+  {
+    "id": "URL",
+    "translation": "URL"
+  },
+  {
+    "id": "Base path",
+    "translation": "Base path"
+  },
+  {
+    "id": "Path",
+    "translation": "Path"
+  },
+  {
+    "id": "display full description of each API",
+    "translation": "display full description of each API"
+  },
+  {
+    "id": "An API host must be provided.",
+    "translation": "An API host must be provided."
+  },
+  {
+    "id": "Request accepted, but processing not completed yet.",
+    "translation": "Request accepted, but processing not completed yet."
+  },
+  {
+    "id": "{{.ok}} invoked /{{.namespace}}/{{.name}}, but the request has not yet finished, with id {{.id}}\n",
+    "translation": "{{.ok}} invoked /{{.namespace}}/{{.name}}, but the request has not yet finished, with id {{.id}}\n"
+  },
+  {
+    "id": "treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action",
+    "translation": "treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"
+  },
+  {
+    "id": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'.",
+    "translation": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
+  },
+  {
+    "id": "API action does not exist",
+    "translation": "API action does not exist"
+  },
+  {
+    "id": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+    "translation": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action."
+  },
+  {
+    "id": "Invalid configuration. The x-openwhisk stanza is missing.",
+    "translation": "Invalid configuration. The x-openwhisk stanza is missing."
+  },
+  {
+    "id": "Internal error. Missing value stanza in API configuration response",
+    "translation": "Internal error. Missing value stanza in API configuration response"
+  },
+  {
+    "id": "Internal error. Missing apidoc stanza in API configuration",
+    "translation": "Internal error. Missing apidoc stanza in API configuration"
+  },
+  {
+    "id": "Missing operationId field in API configuration for operation {{.op}}",
+    "translation": "Missing operationId field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk stanza in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk stanza in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.namespace field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.namespace field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.action field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.action field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.url field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.url field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "work with APIs",
+    "translation": "work with APIs"
+  },
+  {
+    "id": "create a new API",
+    "translation": "create a new API"
+  },
+  {
+    "id": "get API details",
+    "translation": "get API details"
+  },
+  {
+    "id": "delete an API",
+    "translation": "delete an API"
+  },
+  {
+    "id": "list APIs",
+    "translation": "list APIs"
+  },
+  {
+    "id": "Set the web action response TYPE. Possible values are html, http, json, text, svg",
+    "translation": "Set the web action response TYPE. Possible values are html, http, json, text, svg"
+  }
+]
diff --git a/wski18n/resources/es_ES.all.json b/wski18n/resources/es_ES.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/es_ES.all.json
diff --git a/wski18n/resources/fr_FR.all.json b/wski18n/resources/fr_FR.all.json
new file mode 100644
index 0000000..55e81ef
--- /dev/null
+++ b/wski18n/resources/fr_FR.all.json
@@ -0,0 +1,6 @@
+[
+  {
+    "id": "bypass certificate checking",
+    "translation": "Some translation in French"
+  }
+]
diff --git a/wski18n/resources/it_IT.all.json b/wski18n/resources/it_IT.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/it_IT.all.json
diff --git a/wski18n/resources/ja_JA.all.json b/wski18n/resources/ja_JA.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/ja_JA.all.json
diff --git a/wski18n/resources/ko_KR.all.json b/wski18n/resources/ko_KR.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/ko_KR.all.json
diff --git a/wski18n/resources/pt_BR.all.json b/wski18n/resources/pt_BR.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/pt_BR.all.json
diff --git a/wski18n/resources/zh_Hans.all.json b/wski18n/resources/zh_Hans.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/zh_Hans.all.json
diff --git a/wski18n/resources/zh_Hant.all.json b/wski18n/resources/zh_Hant.all.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wski18n/resources/zh_Hant.all.json