TBR: ref: namespace_browser: Move v.io/x/ref/tools to v.io/x/ref/cmd.

This is part of the v.io reorganization.  cmd is the standard
go directory for commandline binaries.  We actually have two:
cmd for regular command line tools, and services for servers.

Note, I am temporarily duplicating the vdl tool for ease of transition.

MultiPart: 4/8

Change-Id: I1880ea23f643b60d315b14e2695c63932fe99625
diff --git a/cmd/GO.PACKAGE b/cmd/GO.PACKAGE
new file mode 100644
index 0000000..5100003
--- /dev/null
+++ b/cmd/GO.PACKAGE
@@ -0,0 +1,8 @@
+{
+	"dependencies": {
+		"incoming": [
+			{"allow": "v.io/x/ref/cmd/..."},
+			{"deny": "..."}
+		]
+	}
+}
diff --git a/tools/application/doc.go b/cmd/application/doc.go
similarity index 100%
rename from tools/application/doc.go
rename to cmd/application/doc.go
diff --git a/tools/application/impl.go b/cmd/application/impl.go
similarity index 100%
rename from tools/application/impl.go
rename to cmd/application/impl.go
diff --git a/tools/application/impl_test.go b/cmd/application/impl_test.go
similarity index 100%
rename from tools/application/impl_test.go
rename to cmd/application/impl_test.go
diff --git a/tools/application/main.go b/cmd/application/main.go
similarity index 100%
rename from tools/application/main.go
rename to cmd/application/main.go
diff --git a/tools/binary/doc.go b/cmd/binary/doc.go
similarity index 100%
rename from tools/binary/doc.go
rename to cmd/binary/doc.go
diff --git a/tools/binary/impl.go b/cmd/binary/impl.go
similarity index 100%
rename from tools/binary/impl.go
rename to cmd/binary/impl.go
diff --git a/tools/binary/impl_test.go b/cmd/binary/impl_test.go
similarity index 100%
rename from tools/binary/impl_test.go
rename to cmd/binary/impl_test.go
diff --git a/tools/binary/main.go b/cmd/binary/main.go
similarity index 100%
rename from tools/binary/main.go
rename to cmd/binary/main.go
diff --git a/tools/build/doc.go b/cmd/build/doc.go
similarity index 100%
rename from tools/build/doc.go
rename to cmd/build/doc.go
diff --git a/tools/build/impl.go b/cmd/build/impl.go
similarity index 100%
rename from tools/build/impl.go
rename to cmd/build/impl.go
diff --git a/tools/build/impl_test.go b/cmd/build/impl_test.go
similarity index 96%
rename from tools/build/impl_test.go
rename to cmd/build/impl_test.go
index f4bd30f..1213aef 100644
--- a/tools/build/impl_test.go
+++ b/cmd/build/impl_test.go
@@ -75,7 +75,7 @@
 	cmd.Init(nil, &stdout, &stderr)
 
 	// Test the 'Build' command.
-	if err := cmd.Execute([]string{"build", naming.JoinAddressName(endpoint.String(), ""), "v.io/x/ref/tools/build"}); err != nil {
+	if err := cmd.Execute([]string{"build", naming.JoinAddressName(endpoint.String(), ""), "v.io/x/ref/cmd/build"}); err != nil {
 		t.Fatalf("%v", err)
 	}
 	if expected, got := "", strings.TrimSpace(stdout.String()); got != expected {
diff --git a/tools/build/main.go b/cmd/build/main.go
similarity index 100%
rename from tools/build/main.go
rename to cmd/build/main.go
diff --git a/tools/debug/debug_v23_test.go b/cmd/debug/debug_v23_test.go
similarity index 94%
rename from tools/debug/debug_v23_test.go
rename to cmd/debug/debug_v23_test.go
index f4beb95..a56051c 100644
--- a/tools/debug/debug_v23_test.go
+++ b/cmd/debug/debug_v23_test.go
@@ -18,7 +18,7 @@
 func V23TestDebugGlob(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	inv := binary.Start("glob", "__debug/*")
 
 	var want string
@@ -35,7 +35,7 @@
 
 	// Create a temp file before we list the logs.
 	fileName := filepath.Base(i.NewTempFile().Name())
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	output := binary.Start("glob", "__debug/logs/*").Output()
 
 	// The output should contain the filename.
@@ -49,7 +49,7 @@
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
 	path := "__debug/stats/system/hostname"
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	got := binary.Start("stats", "read", path).Output()
 	hostname, err := os.Hostname()
 	if err != nil {
@@ -72,7 +72,7 @@
 func V23TestLogSize(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	testLogData := "This is a test log file"
 	file := createTestLogFile(i, testLogData)
 
@@ -91,7 +91,7 @@
 func V23TestStatsRead(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	testLogData := "This is a test log file\n"
 	file := createTestLogFile(i, testLogData)
 	logName := filepath.Base(file.Name())
@@ -111,7 +111,7 @@
 func V23TestStatsWatch(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	testLogData := "This is a test log file\n"
 	file := createTestLogFile(i, testLogData)
 	logName := filepath.Base(file.Name())
@@ -150,7 +150,7 @@
 func V23TestVTrace(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	logContent := "Hello, world!\n"
 	logPath := "__debug/logs/" + filepath.Base(createTestLogFile(i, logContent).Name())
 	// Create a log file with tracing, read it and check that the resulting trace exists.
@@ -203,7 +203,7 @@
 func V23TestPprof(i *v23tests.T) {
 	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")
 
-	binary := i.BuildGoPkg("v.io/x/ref/tools/debug")
+	binary := i.BuildGoPkg("v.io/x/ref/cmd/debug")
 	inv := binary.Start("pprof", "run", "__debug/pprof", "heap", "--text")
 
 	// Assert that a profile indicating the heap size was written out.
diff --git a/tools/debug/doc.go b/cmd/debug/doc.go
similarity index 100%
rename from tools/debug/doc.go
rename to cmd/debug/doc.go
diff --git a/tools/debug/impl.go b/cmd/debug/impl.go
similarity index 100%
rename from tools/debug/impl.go
rename to cmd/debug/impl.go
diff --git a/tools/debug/main.go b/cmd/debug/main.go
similarity index 100%
rename from tools/debug/main.go
rename to cmd/debug/main.go
diff --git a/tools/debug/v23_test.go b/cmd/debug/v23_test.go
similarity index 100%
rename from tools/debug/v23_test.go
rename to cmd/debug/v23_test.go
diff --git a/tools/findunusedport/main.go b/cmd/findunusedport/main.go
similarity index 100%
rename from tools/findunusedport/main.go
rename to cmd/findunusedport/main.go
diff --git a/tools/gclogs/doc.go b/cmd/gclogs/doc.go
similarity index 100%
rename from tools/gclogs/doc.go
rename to cmd/gclogs/doc.go
diff --git a/tools/gclogs/format.go b/cmd/gclogs/format.go
similarity index 100%
rename from tools/gclogs/format.go
rename to cmd/gclogs/format.go
diff --git a/tools/gclogs/format_test.go b/cmd/gclogs/format_test.go
similarity index 100%
rename from tools/gclogs/format_test.go
rename to cmd/gclogs/format_test.go
diff --git a/tools/gclogs/gclogs.go b/cmd/gclogs/gclogs.go
similarity index 100%
rename from tools/gclogs/gclogs.go
rename to cmd/gclogs/gclogs.go
diff --git a/tools/gclogs/gclogs_test.go b/cmd/gclogs/gclogs_test.go
similarity index 100%
rename from tools/gclogs/gclogs_test.go
rename to cmd/gclogs/gclogs_test.go
diff --git a/tools/gclogs/main.go b/cmd/gclogs/main.go
similarity index 100%
rename from tools/gclogs/main.go
rename to cmd/gclogs/main.go
diff --git a/tools/mgmt/device/devicex b/cmd/mgmt/device/devicex
similarity index 100%
rename from tools/mgmt/device/devicex
rename to cmd/mgmt/device/devicex
diff --git a/tools/mgmt/device/doc.go b/cmd/mgmt/device/doc.go
similarity index 100%
rename from tools/mgmt/device/doc.go
rename to cmd/mgmt/device/doc.go
diff --git a/tools/mgmt/device/impl/acl_fmt.go b/cmd/mgmt/device/impl/acl_fmt.go
similarity index 100%
rename from tools/mgmt/device/impl/acl_fmt.go
rename to cmd/mgmt/device/impl/acl_fmt.go
diff --git a/tools/mgmt/device/impl/acl_impl.go b/cmd/mgmt/device/impl/acl_impl.go
similarity index 100%
rename from tools/mgmt/device/impl/acl_impl.go
rename to cmd/mgmt/device/impl/acl_impl.go
diff --git a/tools/mgmt/device/impl/acl_test.go b/cmd/mgmt/device/impl/acl_test.go
similarity index 98%
rename from tools/mgmt/device/impl/acl_test.go
rename to cmd/mgmt/device/impl/acl_test.go
index 819660f..d49e08c 100644
--- a/tools/mgmt/device/impl/acl_test.go
+++ b/cmd/mgmt/device/impl/acl_test.go
@@ -11,10 +11,10 @@
 	"v.io/v23/services/security/access"
 	"v.io/v23/verror"
 
-	"v.io/x/ref/tools/mgmt/device/impl"
+	"v.io/x/ref/cmd/mgmt/device/impl"
 )
 
-const pkgPath = "v.io/x/ref/tools/mgmt/device/main"
+const pkgPath = "v.io/x/ref/cmd/mgmt/device/main"
 
 var (
 	errOops = verror.Register(pkgPath+".errOops", verror.NoRetry, "oops!")
diff --git a/tools/mgmt/device/impl/associate_impl.go b/cmd/mgmt/device/impl/associate_impl.go
similarity index 100%
rename from tools/mgmt/device/impl/associate_impl.go
rename to cmd/mgmt/device/impl/associate_impl.go
diff --git a/tools/mgmt/device/impl/devicemanager_mock_test.go b/cmd/mgmt/device/impl/devicemanager_mock_test.go
similarity index 100%
rename from tools/mgmt/device/impl/devicemanager_mock_test.go
rename to cmd/mgmt/device/impl/devicemanager_mock_test.go
diff --git a/tools/mgmt/device/impl/impl.go b/cmd/mgmt/device/impl/impl.go
similarity index 100%
rename from tools/mgmt/device/impl/impl.go
rename to cmd/mgmt/device/impl/impl.go
diff --git a/tools/mgmt/device/impl/impl_test.go b/cmd/mgmt/device/impl/impl_test.go
similarity index 99%
rename from tools/mgmt/device/impl/impl_test.go
rename to cmd/mgmt/device/impl/impl_test.go
index 700c3fe..247c40e 100644
--- a/tools/mgmt/device/impl/impl_test.go
+++ b/cmd/mgmt/device/impl/impl_test.go
@@ -15,8 +15,8 @@
 	"v.io/v23/services/mgmt/device"
 	"v.io/v23/verror"
 
+	"v.io/x/ref/cmd/mgmt/device/impl"
 	"v.io/x/ref/security"
-	"v.io/x/ref/tools/mgmt/device/impl"
 )
 
 func TestListCommand(t *testing.T) {
diff --git a/tools/mgmt/device/impl/instance_impl.go b/cmd/mgmt/device/impl/instance_impl.go
similarity index 100%
rename from tools/mgmt/device/impl/instance_impl.go
rename to cmd/mgmt/device/impl/instance_impl.go
diff --git a/tools/mgmt/device/impl/instance_impl_test.go b/cmd/mgmt/device/impl/instance_impl_test.go
similarity index 98%
rename from tools/mgmt/device/impl/instance_impl_test.go
rename to cmd/mgmt/device/impl/instance_impl_test.go
index 7c7df24..8cdcbf9 100644
--- a/tools/mgmt/device/impl/instance_impl_test.go
+++ b/cmd/mgmt/device/impl/instance_impl_test.go
@@ -9,7 +9,7 @@
 	"v.io/v23/naming"
 	"v.io/v23/verror"
 
-	"v.io/x/ref/tools/mgmt/device/impl"
+	"v.io/x/ref/cmd/mgmt/device/impl"
 )
 
 func TestStopCommand(t *testing.T) {
diff --git a/tools/mgmt/device/impl/local_install.go b/cmd/mgmt/device/impl/local_install.go
similarity index 100%
rename from tools/mgmt/device/impl/local_install.go
rename to cmd/mgmt/device/impl/local_install.go
diff --git a/tools/mgmt/device/impl/local_install_test.go b/cmd/mgmt/device/impl/local_install_test.go
similarity index 99%
rename from tools/mgmt/device/impl/local_install_test.go
rename to cmd/mgmt/device/impl/local_install_test.go
index d7b5374..c696198 100644
--- a/tools/mgmt/device/impl/local_install_test.go
+++ b/cmd/mgmt/device/impl/local_install_test.go
@@ -16,7 +16,7 @@
 	"v.io/v23/services/mgmt/application"
 	"v.io/v23/services/mgmt/device"
 
-	"v.io/x/ref/tools/mgmt/device/impl"
+	"v.io/x/ref/cmd/mgmt/device/impl"
 )
 
 func createFile(t *testing.T, path string, contents string) {
diff --git a/tools/mgmt/device/impl/mock_test.go b/cmd/mgmt/device/impl/mock_test.go
similarity index 100%
rename from tools/mgmt/device/impl/mock_test.go
rename to cmd/mgmt/device/impl/mock_test.go
diff --git a/tools/mgmt/device/impl/root.go b/cmd/mgmt/device/impl/root.go
similarity index 100%
rename from tools/mgmt/device/impl/root.go
rename to cmd/mgmt/device/impl/root.go
diff --git a/tools/mgmt/device/impl/util_test.go b/cmd/mgmt/device/impl/util_test.go
similarity index 90%
rename from tools/mgmt/device/impl/util_test.go
rename to cmd/mgmt/device/impl/util_test.go
index ecb1d9a..1914614 100644
--- a/tools/mgmt/device/impl/util_test.go
+++ b/cmd/mgmt/device/impl/util_test.go
@@ -4,9 +4,9 @@
 	"v.io/v23"
 	"v.io/v23/context"
 
+	"v.io/x/ref/cmd/mgmt/device/impl"
 	"v.io/x/ref/lib/testutil"
 	_ "v.io/x/ref/profiles"
-	"v.io/x/ref/tools/mgmt/device/impl"
 )
 
 var gctx *context.T
diff --git a/tools/mgmt/device/main.go b/cmd/mgmt/device/main.go
similarity index 90%
rename from tools/mgmt/device/main.go
rename to cmd/mgmt/device/main.go
index d1182e1..c5714e2 100644
--- a/tools/mgmt/device/main.go
+++ b/cmd/mgmt/device/main.go
@@ -8,8 +8,8 @@
 
 	"v.io/v23"
 
+	"v.io/x/ref/cmd/mgmt/device/impl"
 	_ "v.io/x/ref/profiles/static"
-	"v.io/x/ref/tools/mgmt/device/impl"
 )
 
 func main() {
diff --git a/tools/mgmt/dummy.go b/cmd/mgmt/dummy.go
similarity index 100%
rename from tools/mgmt/dummy.go
rename to cmd/mgmt/dummy.go
diff --git a/tools/mgmt/mgmt_v23_test.go b/cmd/mgmt/mgmt_v23_test.go
similarity index 96%
rename from tools/mgmt/mgmt_v23_test.go
rename to cmd/mgmt/mgmt_v23_test.go
index 779aca2..172ecdb 100644
--- a/tools/mgmt/mgmt_v23_test.go
+++ b/cmd/mgmt/mgmt_v23_test.go
@@ -85,16 +85,16 @@
 	// the device ("alice/myworkstation") can talk to it. ALl of the binaries
 	// that communicate with each other must share this credentials directory.
 	credentials := "VEYRON_CREDENTIALS=" + i.NewTempDir()
-	namespaceBin := i.BuildGoPkg("v.io/x/ref/tools/namespace").WithEnv(credentials)
-	debugBin := i.BuildGoPkg("v.io/x/ref/tools/debug").WithEnv(credentials)
-	deviceBin := i.BuildGoPkg("v.io/x/ref/tools/mgmt/device").WithEnv(credentials)
+	namespaceBin := i.BuildGoPkg("v.io/x/ref/cmd/namespace").WithEnv(credentials)
+	debugBin := i.BuildGoPkg("v.io/x/ref/cmd/debug").WithEnv(credentials)
+	deviceBin := i.BuildGoPkg("v.io/x/ref/cmd/mgmt/device").WithEnv(credentials)
 	devicedBin := i.BuildGoPkg("v.io/x/ref/services/mgmt/device/deviced").WithEnv(credentials)
 	deviceScript := i.BinaryFromPath("device/devicex").WithEnv(credentials)
-	principalBin := i.BuildGoPkg("v.io/x/ref/tools/principal").WithEnv(credentials)
+	principalBin := i.BuildGoPkg("v.io/x/ref/cmd/principal").WithEnv(credentials)
 	binarydBin := i.BuildGoPkg("v.io/x/ref/services/mgmt/binary/binaryd").WithEnv(credentials)
-	binaryBin := i.BuildGoPkg("v.io/x/ref/tools/binary").WithEnv(credentials)
+	binaryBin := i.BuildGoPkg("v.io/x/ref/cmd/binary").WithEnv(credentials)
 	applicationdBin := i.BuildGoPkg("v.io/x/ref/services/mgmt/application/applicationd").WithEnv(credentials)
-	applicationBin := i.BuildGoPkg("v.io/x/ref/tools/application").WithEnv(credentials)
+	applicationBin := i.BuildGoPkg("v.io/x/ref/cmd/application").WithEnv(credentials)
 
 	appDName := "applicationd"
 	devicedAppName := filepath.Join(appDName, "deviced", "test")
diff --git a/tools/mgmt/shell/lib/pkg.go b/cmd/mgmt/shell/lib/pkg.go
similarity index 100%
rename from tools/mgmt/shell/lib/pkg.go
rename to cmd/mgmt/shell/lib/pkg.go
diff --git a/tools/mgmt/shell/lib/shell.sh b/cmd/mgmt/shell/lib/shell.sh
similarity index 100%
rename from tools/mgmt/shell/lib/shell.sh
rename to cmd/mgmt/shell/lib/shell.sh
diff --git a/tools/mgmt/shell/lib/shell_test.sh b/cmd/mgmt/shell/lib/shell_test.sh
similarity index 97%
rename from tools/mgmt/shell/lib/shell_test.sh
rename to cmd/mgmt/shell/lib/shell_test.sh
index e99a845..51e22b4 100755
--- a/tools/mgmt/shell/lib/shell_test.sh
+++ b/cmd/mgmt/shell/lib/shell_test.sh
@@ -6,7 +6,7 @@
 # handler must call shell_test::at_exit to clean up all temporary
 # files and directories created by this library.
 
-source "$(go list -f {{.Dir}} v.io/x/ref/tools/mgmt)/shell/lib/shell.sh"
+source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell/lib/shell.sh"
 
 trap shell_test::at_exit INT TERM EXIT
 
@@ -221,7 +221,7 @@
 shell_test::credentials() {
   [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
     || shell_test::fail "credentials called when running under enable_agent"
-  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/principal')"
+  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
   local -r CRED=$(shell::tmp_dir)
   "${PRINCIPAL_BIN}" create --overwrite=true "${CRED}" "$1" >/dev/null || shell_test::fail "line ${LINENO}: create failed"
   echo "${CRED}"
@@ -237,7 +237,7 @@
   [[ ! -n ${shell_test_RUNNING_UNDER_AGENT+1} ]] \
     || shell_test::fail "forkcredentials called when running under enable_agent"
 
-  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/principal')"
+  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
   local -r FORKCRED=$(shell::tmp_dir)
   "${PRINCIPAL_BIN}" create --overwrite=true "${FORKCRED}" self >/dev/null || shell_test::fail "line ${LINENO}: create failed"
   "${PRINCIPAL_BIN}" --veyron.credentials="$1" bless --require_caveats=false "${FORKCRED}" "$2" >blessing || shell_test::fail "line ${LINENO}: bless failed"
@@ -268,6 +268,6 @@
     VEYRON_CREDENTIALS="${WORKDIR}/credentials" exec ${AGENTD} --no_passphrase --additional_principals="${WORKDIR}/childcredentials" bash -"$-" "$0" "$@"
     shell_test::fail "failed to run test under agent"
   else
-    VRUN="$(shell_test::build_go_binary 'v.io/x/ref/tools/vrun')"
+    VRUN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/vrun')"
   fi
 }
diff --git a/tools/mgmt/shell/lib/test.sh b/cmd/mgmt/shell/lib/test.sh
similarity index 96%
rename from tools/mgmt/shell/lib/test.sh
rename to cmd/mgmt/shell/lib/test.sh
index a2a1e5c..ccd7351 100755
--- a/tools/mgmt/shell/lib/test.sh
+++ b/cmd/mgmt/shell/lib/test.sh
@@ -4,7 +4,7 @@
 # Unit tests for the shell functions in this directory
 #
 
-source "$(go list -f {{.Dir}} v.io/x/ref/tools/mgmt)/shell/lib/shell_test.sh"
+source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell/lib/shell_test.sh"
 
 test_assert() {
   shell_test::assert_eq "foo" "foo" "${LINENO}"
@@ -55,7 +55,7 @@
 test_credentials() {
   local -r CRED=$(shell_test::credentials alice)
 
-  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/principal')"
+  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
 
   "${PRINCIPAL_BIN}" --veyron.credentials="${CRED}" dump >alice.dump ||  shell_test::fail "line ${LINENO}: ${PRINCIPAL_BIN} dump ${CRED} failed"
   cat alice.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice.dump | rmpublickey failed"
@@ -78,7 +78,7 @@
   local -r CRED=$(shell_test::credentials alice)
   local -r FORKCRED=$(shell_test::forkcredentials "${CRED}" fork)
 
-  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/principal')"
+  local -r PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
 
   "${PRINCIPAL_BIN}" --veyron.credentials="${FORKCRED}" dump >alice.dump ||  shell_test::fail "line ${LINENO}: ${PRINCIPAL_BIN} dump ${CRED} failed"
   cat alice.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice.dump | rmpublickey failed"
diff --git a/tools/mgmt/suid_test.sh b/cmd/mgmt/suid_test.sh
similarity index 95%
rename from tools/mgmt/suid_test.sh
rename to cmd/mgmt/suid_test.sh
index 3537cd3..febd73a 100755
--- a/tools/mgmt/suid_test.sh
+++ b/cmd/mgmt/suid_test.sh
@@ -40,7 +40,7 @@
   umask 066
 fi
 
- source "$(go list -f {{.Dir}} v.io/x/ref/tools/mgmt)/shell/lib/shell_test.sh"
+ source "$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt)/shell/lib/shell_test.sh"
 
 # Run the test under the security agent.
 shell_test::enable_agent "$@"
@@ -50,18 +50,18 @@
 build() {
   echo ">> Building binaries"
   BINARYD_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mgmt/binary/binaryd')"
-  BINARY_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/binary')"
+  BINARY_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/binary')"
   APPLICATIOND_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mgmt/application/applicationd')"
-  APPLICATION_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/application')"
+  APPLICATION_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/application')"
   AGENTD_BIN="$(shell_test::build_go_binary 'v.io/x/ref/security/agent/agentd')"
   SUIDHELPER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mgmt/suidhelper')"
   INITHELPER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mgmt/inithelper')"
   DEVICEMANAGER_BIN="$(shell_test::build_go_binary 'v.io/x/ref/services/mgmt/device/deviced')"
-  DEVICE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/mgmt/device')"
-  NAMESPACE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/namespace')"
-  PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/principal')"
-  DEBUG_BIN="$(shell_test::build_go_binary 'v.io/x/ref/tools/debug')"
-  DEVICE_SCRIPT="$(go list -f {{.Dir}} v.io/x/ref/tools/mgmt/device)/devicex"
+  DEVICE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/mgmt/device')"
+  NAMESPACE_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/namespace')"
+  PRINCIPAL_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/principal')"
+  DEBUG_BIN="$(shell_test::build_go_binary 'v.io/x/ref/cmd/debug')"
+  DEVICE_SCRIPT="$(go list -f {{.Dir}} v.io/x/ref/cmd/mgmt/device)/devicex"
 }
 
 # TODO(caprita): Move to shell_tesh.sh
diff --git a/tools/mgmt/v23_test.go b/cmd/mgmt/v23_test.go
similarity index 100%
rename from tools/mgmt/v23_test.go
rename to cmd/mgmt/v23_test.go
diff --git a/tools/mgmt/vbash b/cmd/mgmt/vbash
similarity index 98%
rename from tools/mgmt/vbash
rename to cmd/mgmt/vbash
index 59f0b18..a1614b9 100755
--- a/tools/mgmt/vbash
+++ b/cmd/mgmt/vbash
@@ -29,7 +29,7 @@
 
 set -e
 
-readonly BIN_PACKAGES=(v.io/x/ref/tools/principal v.io/x/ref/security/agent/agentd)
+readonly BIN_PACKAGES=(v.io/x/ref/cmd/principal v.io/x/ref/security/agent/agentd)
 BIN_NAMES=(${BIN_PACKAGES[@]})
 for (( i=0; i<${#BIN_PACKAGES[@]}; i++ )); do
   BIN_NAMES[$i]=$(basename "${BIN_PACKAGES[$i]}")
diff --git a/tools/mounttable/doc.go b/cmd/mounttable/doc.go
similarity index 100%
rename from tools/mounttable/doc.go
rename to cmd/mounttable/doc.go
diff --git a/tools/mounttable/impl.go b/cmd/mounttable/impl.go
similarity index 100%
rename from tools/mounttable/impl.go
rename to cmd/mounttable/impl.go
diff --git a/tools/mounttable/impl_test.go b/cmd/mounttable/impl_test.go
similarity index 100%
rename from tools/mounttable/impl_test.go
rename to cmd/mounttable/impl_test.go
diff --git a/tools/mounttable/main.go b/cmd/mounttable/main.go
similarity index 100%
rename from tools/mounttable/main.go
rename to cmd/mounttable/main.go
diff --git a/tools/namespace/doc.go b/cmd/namespace/doc.go
similarity index 100%
rename from tools/namespace/doc.go
rename to cmd/namespace/doc.go
diff --git a/tools/namespace/impl.go b/cmd/namespace/impl.go
similarity index 100%
rename from tools/namespace/impl.go
rename to cmd/namespace/impl.go
diff --git a/tools/namespace/main.go b/cmd/namespace/main.go
similarity index 100%
rename from tools/namespace/main.go
rename to cmd/namespace/main.go
diff --git a/tools/naming/simulator/commands.go b/cmd/naming/simulator/commands.go
similarity index 100%
rename from tools/naming/simulator/commands.go
rename to cmd/naming/simulator/commands.go
diff --git a/tools/naming/simulator/driver.go b/cmd/naming/simulator/driver.go
similarity index 100%
rename from tools/naming/simulator/driver.go
rename to cmd/naming/simulator/driver.go
diff --git a/tools/naming/simulator/driver_test.go b/cmd/naming/simulator/driver_test.go
similarity index 100%
rename from tools/naming/simulator/driver_test.go
rename to cmd/naming/simulator/driver_test.go
diff --git a/tools/naming/simulator/shell_functions.go b/cmd/naming/simulator/shell_functions.go
similarity index 100%
rename from tools/naming/simulator/shell_functions.go
rename to cmd/naming/simulator/shell_functions.go
diff --git a/tools/naming/simulator/simulator_v23_test.go b/cmd/naming/simulator/simulator_v23_test.go
similarity index 95%
rename from tools/naming/simulator/simulator_v23_test.go
rename to cmd/naming/simulator/simulator_v23_test.go
index 4b68bb5..57c86b1 100644
--- a/tools/naming/simulator/simulator_v23_test.go
+++ b/cmd/naming/simulator/simulator_v23_test.go
@@ -23,7 +23,7 @@
 }
 
 func V23TestSimulator(t *v23tests.T) {
-	binary := t.BuildGoPkg("v.io/x/ref/tools/naming/simulator")
+	binary := t.BuildGoPkg("v.io/x/ref/cmd/naming/simulator")
 	files, err := ioutil.ReadDir("./testdata")
 	if err != nil {
 		t.Fatal(err)
diff --git a/tools/naming/simulator/testdata/ambiguity.scr b/cmd/naming/simulator/testdata/ambiguity.scr
similarity index 100%
rename from tools/naming/simulator/testdata/ambiguity.scr
rename to cmd/naming/simulator/testdata/ambiguity.scr
diff --git a/tools/naming/simulator/testdata/echo.scr b/cmd/naming/simulator/testdata/echo.scr
similarity index 100%
rename from tools/naming/simulator/testdata/echo.scr
rename to cmd/naming/simulator/testdata/echo.scr
diff --git a/tools/naming/simulator/testdata/json_example.scr b/cmd/naming/simulator/testdata/json_example.scr
similarity index 100%
rename from tools/naming/simulator/testdata/json_example.scr
rename to cmd/naming/simulator/testdata/json_example.scr
diff --git a/tools/naming/simulator/testdata/mt_complex.scr b/cmd/naming/simulator/testdata/mt_complex.scr
similarity index 100%
rename from tools/naming/simulator/testdata/mt_complex.scr
rename to cmd/naming/simulator/testdata/mt_complex.scr
diff --git a/tools/naming/simulator/testdata/mt_simple.scr b/cmd/naming/simulator/testdata/mt_simple.scr
similarity index 100%
rename from tools/naming/simulator/testdata/mt_simple.scr
rename to cmd/naming/simulator/testdata/mt_simple.scr
diff --git a/tools/naming/simulator/testdata/proxy.scr b/cmd/naming/simulator/testdata/proxy.scr
similarity index 100%
rename from tools/naming/simulator/testdata/proxy.scr
rename to cmd/naming/simulator/testdata/proxy.scr
diff --git a/tools/naming/simulator/testdata/public_echo.scr b/cmd/naming/simulator/testdata/public_echo.scr
similarity index 100%
rename from tools/naming/simulator/testdata/public_echo.scr
rename to cmd/naming/simulator/testdata/public_echo.scr
diff --git a/tools/naming/simulator/v23_test.go b/cmd/naming/simulator/v23_test.go
similarity index 100%
rename from tools/naming/simulator/v23_test.go
rename to cmd/naming/simulator/v23_test.go
diff --git a/tools/principal/bless.go b/cmd/principal/bless.go
similarity index 100%
rename from tools/principal/bless.go
rename to cmd/principal/bless.go
diff --git a/tools/principal/caveat.go b/cmd/principal/caveat.go
similarity index 100%
rename from tools/principal/caveat.go
rename to cmd/principal/caveat.go
diff --git a/tools/principal/doc.go b/cmd/principal/doc.go
similarity index 100%
rename from tools/principal/doc.go
rename to cmd/principal/doc.go
diff --git a/tools/principal/main.go b/cmd/principal/main.go
similarity index 100%
rename from tools/principal/main.go
rename to cmd/principal/main.go
diff --git a/tools/principal/main_darwin.go b/cmd/principal/main_darwin.go
similarity index 100%
rename from tools/principal/main_darwin.go
rename to cmd/principal/main_darwin.go
diff --git a/tools/principal/main_linux.go b/cmd/principal/main_linux.go
similarity index 100%
rename from tools/principal/main_linux.go
rename to cmd/principal/main_linux.go
diff --git a/tools/principal/main_nacl.go b/cmd/principal/main_nacl.go
similarity index 100%
rename from tools/principal/main_nacl.go
rename to cmd/principal/main_nacl.go
diff --git a/tools/principal/principal_v23_test.go b/cmd/principal/principal_v23_test.go
similarity index 96%
rename from tools/principal/principal_v23_test.go
rename to cmd/principal/principal_v23_test.go
index b4a9ade..d093ef6 100644
--- a/tools/principal/principal_v23_test.go
+++ b/cmd/principal/principal_v23_test.go
@@ -50,7 +50,7 @@
 		aliceBlessingFile = filepath.Join(outputDir, "aliceself")
 	)
 
-	bin := t.BuildGoPkg("v.io/x/ref/tools/principal")
+	bin := t.BuildGoPkg("v.io/x/ref/cmd/principal")
 	bin.Start("create", aliceDir, "alice").WaitOrDie(os.Stdout, os.Stderr)
 
 	bin = bin.WithEnv("VEYRON_CREDENTIALS=" + aliceDir)
@@ -70,7 +70,7 @@
 func V23TestStore(t *v23tests.T) {
 	var (
 		outputDir   = t.NewTempDir()
-		bin         = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin         = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		aliceDir    = filepath.Join(outputDir, "alice")
 		aliceFriend = filepath.Join(outputDir, "alice.bless")
 		bobDir      = filepath.Join(outputDir, "bob")
@@ -108,7 +108,7 @@
 func V23TestDump(t *v23tests.T) {
 	var (
 		outputDir = t.NewTempDir()
-		bin       = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin       = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		aliceDir  = filepath.Join(outputDir, "alice")
 	)
 
@@ -150,7 +150,7 @@
 func V23TestRecvBlessings(t *v23tests.T) {
 	var (
 		outputDir = t.NewTempDir()
-		bin       = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin       = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		aliceDir  = filepath.Join(outputDir, "alice")
 		carolDir  = filepath.Join(outputDir, "carol")
 	)
@@ -236,7 +236,7 @@
 func V23TestFork(t *v23tests.T) {
 	var (
 		outputDir             = t.NewTempDir()
-		bin                   = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin                   = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		aliceDir              = filepath.Join(outputDir, "alice")
 		alicePhoneDir         = filepath.Join(outputDir, "alice-phone")
 		alicePhoneCalendarDir = filepath.Join(outputDir, "alice-phone-calendar")
@@ -323,7 +323,7 @@
 func V23TestCreate(t *v23tests.T) {
 	var (
 		outputDir = t.NewTempDir()
-		bin       = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin       = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		aliceDir  = filepath.Join(outputDir, "alice")
 	)
 
@@ -346,7 +346,7 @@
 		aliceBlessingFile = filepath.Join(outputDir, "aliceself")
 	)
 
-	bin := t.BuildGoPkg("v.io/x/ref/tools/principal")
+	bin := t.BuildGoPkg("v.io/x/ref/cmd/principal")
 	bin.Start("create", aliceDir, "alice").WaitOrDie(os.Stdout, os.Stderr)
 
 	bin = bin.WithEnv("VEYRON_CREDENTIALS=" + aliceDir)
@@ -374,7 +374,7 @@
 func V23TestForkWithoutVDLPATH(t *v23tests.T) {
 	var (
 		parent = t.NewTempDir()
-		bin    = t.BuildGoPkg("v.io/x/ref/tools/principal").WithEnv("VANADIUM_ROOT=''", "VDLPATH=''")
+		bin    = t.BuildGoPkg("v.io/x/ref/cmd/principal").WithEnv("VANADIUM_ROOT=''", "VDLPATH=''")
 	)
 	if err := bin.Start("create", parent, "parent").Wait(os.Stdout, os.Stderr); err != nil {
 		t.Fatalf("create %q failed: %v", parent, err)
@@ -388,7 +388,7 @@
 	var (
 		parent = t.NewTempDir()
 		child  = t.NewTempDir()
-		bin    = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin    = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		buf    bytes.Buffer
 	)
 	if err := bin.Start("create", parent, "parent").Wait(os.Stdout, os.Stderr); err != nil {
@@ -411,7 +411,7 @@
 
 func V23TestBless(t *v23tests.T) {
 	var (
-		bin      = t.BuildGoPkg("v.io/x/ref/tools/principal")
+		bin      = t.BuildGoPkg("v.io/x/ref/cmd/principal")
 		dir      = t.NewTempDir()
 		aliceDir = filepath.Join(dir, "alice")
 		bobDir   = filepath.Join(dir, "bob")
diff --git a/tools/principal/v23_test.go b/cmd/principal/v23_test.go
similarity index 100%
rename from tools/principal/v23_test.go
rename to cmd/principal/v23_test.go
diff --git a/tools/profile/doc.go b/cmd/profile/doc.go
similarity index 100%
rename from tools/profile/doc.go
rename to cmd/profile/doc.go
diff --git a/tools/profile/impl.go b/cmd/profile/impl.go
similarity index 100%
rename from tools/profile/impl.go
rename to cmd/profile/impl.go
diff --git a/tools/profile/impl_test.go b/cmd/profile/impl_test.go
similarity index 100%
rename from tools/profile/impl_test.go
rename to cmd/profile/impl_test.go
diff --git a/tools/profile/main.go b/cmd/profile/main.go
similarity index 100%
rename from tools/profile/main.go
rename to cmd/profile/main.go
diff --git a/tools/servicerunner/main.go b/cmd/servicerunner/main.go
similarity index 100%
rename from tools/servicerunner/main.go
rename to cmd/servicerunner/main.go
diff --git a/tools/servicerunner/servicerunner_test.go b/cmd/servicerunner/servicerunner_test.go
similarity index 97%
rename from tools/servicerunner/servicerunner_test.go
rename to cmd/servicerunner/servicerunner_test.go
index 38959bc..6f8d0da 100644
--- a/tools/servicerunner/servicerunner_test.go
+++ b/cmd/servicerunner/servicerunner_test.go
@@ -26,7 +26,7 @@
 
 	bin := path.Join(tmpdir, "servicerunner")
 	fmt.Println("Building", bin)
-	err = exec.Command("v23", "go", "build", "-o", bin, "v.io/x/ref/tools/servicerunner").Run()
+	err = exec.Command("v23", "go", "build", "-o", bin, "v.io/x/ref/cmd/servicerunner").Run()
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/tools/uniqueid/doc.go b/cmd/uniqueid/doc.go
similarity index 100%
rename from tools/uniqueid/doc.go
rename to cmd/uniqueid/doc.go
diff --git a/tools/uniqueid/main.go b/cmd/uniqueid/main.go
similarity index 100%
rename from tools/uniqueid/main.go
rename to cmd/uniqueid/main.go
diff --git a/cmd/vdl/arith_test.go b/cmd/vdl/arith_test.go
new file mode 100644
index 0000000..ddc636e
--- /dev/null
+++ b/cmd/vdl/arith_test.go
@@ -0,0 +1,481 @@
+package main_test
+
+// This test assumes the vdl packages under veyron2/vdl/testdata have been
+// compiled using the vdl binary, and runs end-to-end ipc tests against the
+// generated output.  It's meant as a final sanity check of the vdl compiler; by
+// using the compiled results we're behaving as an end-user would behave.
+
+import (
+	"errors"
+	"math"
+	"reflect"
+	"testing"
+
+	"v.io/v23"
+	"v.io/v23/context"
+	"v.io/v23/ipc"
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/testdata/arith"
+	"v.io/x/ref/lib/vdl/testdata/base"
+
+	"v.io/x/ref/lib/testutil"
+	_ "v.io/x/ref/profiles"
+)
+
+var generatedError = errors.New("generated error")
+
+func newServer(ctx *context.T) ipc.Server {
+	s, err := v23.NewServer(ctx)
+	if err != nil {
+		panic(err)
+	}
+	return s
+}
+
+// serverArith implements the arith.Arith interface.
+type serverArith struct{}
+
+func (*serverArith) Add(_ ipc.ServerCall, A, B int32) (int32, error) {
+	return A + B, nil
+}
+
+func (*serverArith) DivMod(_ ipc.ServerCall, A, B int32) (int32, int32, error) {
+	return A / B, A % B, nil
+}
+
+func (*serverArith) Sub(_ ipc.ServerCall, args base.Args) (int32, error) {
+	return args.A - args.B, nil
+}
+
+func (*serverArith) Mul(_ ipc.ServerCall, nestedArgs base.NestedArgs) (int32, error) {
+	return nestedArgs.Args.A * nestedArgs.Args.B, nil
+}
+
+func (*serverArith) Count(ctx arith.ArithCountContext, start int32) error {
+	const kNum = 1000
+	for i := int32(0); i < kNum; i++ {
+		if err := ctx.SendStream().Send(start + i); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (*serverArith) StreamingAdd(ctx arith.ArithStreamingAddContext) (int32, error) {
+	var total int32
+	for ctx.RecvStream().Advance() {
+		value := ctx.RecvStream().Value()
+		total += value
+		ctx.SendStream().Send(total)
+	}
+	return total, ctx.RecvStream().Err()
+}
+
+func (*serverArith) GenError(_ ipc.ServerCall) error {
+	return generatedError
+}
+
+func (*serverArith) QuoteAny(_ ipc.ServerCall, any *vdl.Value) (*vdl.Value, error) {
+	return vdl.StringValue(any.String()), nil
+}
+
+type serverCalculator struct {
+	serverArith
+}
+
+func (*serverCalculator) Sine(_ ipc.ServerCall, angle float64) (float64, error) {
+	return math.Sin(angle), nil
+}
+
+func (*serverCalculator) Cosine(_ ipc.ServerCall, angle float64) (float64, error) {
+	return math.Cos(angle), nil
+}
+
+func (*serverCalculator) Exp(_ ipc.ServerCall, x float64) (float64, error) {
+	return math.Exp(x), nil
+}
+
+func (*serverCalculator) On(_ ipc.ServerCall) error {
+	return nil
+}
+
+func (*serverCalculator) Off(_ ipc.ServerCall) error {
+	return nil
+}
+
+func TestCalculator(t *testing.T) {
+	ctx, shutdown := testutil.InitForTest()
+	defer shutdown()
+
+	server := newServer(ctx)
+	eps, err := server.Listen(v23.GetListenSpec(ctx))
+	if err := server.Serve("", arith.CalculatorServer(&serverCalculator{}), nil); err != nil {
+		t.Fatal(err)
+	}
+	root := eps[0].Name()
+	// Synchronous calls
+	calculator := arith.CalculatorClient(root)
+	sine, err := calculator.Sine(ctx, 0)
+	if err != nil {
+		t.Errorf("Sine: got %q but expected no error", err)
+	}
+	if sine != 0 {
+		t.Errorf("Sine: expected 0 got %f", sine)
+	}
+	cosine, err := calculator.Cosine(ctx, 0)
+	if err != nil {
+		t.Errorf("Cosine: got %q but expected no error", err)
+	}
+	if cosine != 1 {
+		t.Errorf("Cosine: expected 1 got %f", cosine)
+	}
+
+	ar := arith.ArithClient(root)
+	sum, err := ar.Add(ctx, 7, 8)
+	if err != nil {
+		t.Errorf("Add: got %q but expected no error", err)
+	}
+	if sum != 15 {
+		t.Errorf("Add: expected 15 got %d", sum)
+	}
+	ar = calculator
+	sum, err = ar.Add(ctx, 7, 8)
+	if err != nil {
+		t.Errorf("Add: got %q but expected no error", err)
+	}
+	if sum != 15 {
+		t.Errorf("Add: expected 15 got %d", sum)
+	}
+
+	trig := arith.TrigonometryClient(root)
+	cosine, err = trig.Cosine(ctx, 0)
+	if err != nil {
+		t.Errorf("Cosine: got %q but expected no error", err)
+	}
+	if cosine != 1 {
+		t.Errorf("Cosine: expected 1 got %f", cosine)
+	}
+
+	// Test auto-generated methods.
+	serverStub := arith.CalculatorServer(&serverCalculator{})
+	expectDesc(t, serverStub.Describe__(), []ipc.InterfaceDesc{
+		{
+			Name:    "Calculator",
+			PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+			Embeds: []ipc.EmbedDesc{
+				{
+					Name:    "Arith",
+					PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+				},
+				{
+					Name:    "AdvancedMath",
+					PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+				},
+			},
+			Methods: []ipc.MethodDesc{
+				{Name: "On"},
+				{Name: "Off", Tags: []*vdl.Value{vdl.StringValue("offtag")}},
+			},
+		},
+		{
+			Name:    "Arith",
+			PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+			Methods: []ipc.MethodDesc{
+				{
+					Name:    "Add",
+					InArgs:  []ipc.ArgDesc{{Name: "a"}, {Name: "b"}},
+					OutArgs: []ipc.ArgDesc{{}},
+				},
+				{
+					Name:    "DivMod",
+					InArgs:  []ipc.ArgDesc{{Name: "a"}, {Name: "b"}},
+					OutArgs: []ipc.ArgDesc{{Name: "quot"}, {Name: "rem"}},
+				},
+				{
+					Name:    "Sub",
+					InArgs:  []ipc.ArgDesc{{Name: "args"}},
+					OutArgs: []ipc.ArgDesc{{}},
+				},
+				{
+					Name:    "Mul",
+					InArgs:  []ipc.ArgDesc{{Name: "nested"}},
+					OutArgs: []ipc.ArgDesc{{}},
+				},
+				{
+					Name: "GenError",
+					Tags: []*vdl.Value{vdl.StringValue("foo"), vdl.StringValue("barz"), vdl.StringValue("hello"), vdl.Int32Value(129), vdl.Uint64Value(0x24)},
+				},
+				{
+					Name:   "Count",
+					InArgs: []ipc.ArgDesc{{Name: "start"}},
+				},
+				{
+					Name:    "StreamingAdd",
+					OutArgs: []ipc.ArgDesc{{Name: "total"}},
+				},
+				{
+					Name:    "QuoteAny",
+					InArgs:  []ipc.ArgDesc{{Name: "a"}},
+					OutArgs: []ipc.ArgDesc{{}},
+				},
+			},
+		},
+		{
+			Name:    "AdvancedMath",
+			PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+			Embeds: []ipc.EmbedDesc{
+				{
+					Name:    "Trigonometry",
+					PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+				},
+				{
+					Name:    "Exp",
+					PkgPath: "v.io/x/ref/lib/vdl/testdata/arith/exp",
+				}},
+		},
+		{
+			Name:    "Trigonometry",
+			PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+			Doc:     "// Trigonometry is an interface that specifies a couple trigonometric functions.",
+			Methods: []ipc.MethodDesc{
+				{
+					Name: "Sine",
+					InArgs: []ipc.ArgDesc{
+						{"angle", ``}, // float64
+					},
+					OutArgs: []ipc.ArgDesc{
+						{"", ``}, // float64
+					},
+				},
+				{
+					Name: "Cosine",
+					InArgs: []ipc.ArgDesc{
+						{"angle", ``}, // float64
+					},
+					OutArgs: []ipc.ArgDesc{
+						{"", ``}, // float64
+					},
+				},
+			},
+		},
+		{
+			Name:    "Exp",
+			PkgPath: "v.io/x/ref/lib/vdl/testdata/arith/exp",
+			Methods: []ipc.MethodDesc{
+				{
+					Name: "Exp",
+					InArgs: []ipc.ArgDesc{
+						{"x", ``}, // float64
+					},
+					OutArgs: []ipc.ArgDesc{
+						{"", ``}, // float64
+					},
+				},
+			},
+		},
+	})
+}
+
+func TestArith(t *testing.T) {
+	ctx, shutdown := testutil.InitForTest()
+	defer shutdown()
+
+	// TODO(bprosnitz) Split this test up -- it is quite long and hard to debug.
+
+	// We try a few types of dispatchers on the server side, to verify that
+	// anything dispatching to Arith or an interface embedding Arith (like
+	// Calculator) works for a client looking to talk to an Arith service.
+	objects := []interface{}{
+		arith.ArithServer(&serverArith{}),
+		arith.ArithServer(&serverCalculator{}),
+		arith.CalculatorServer(&serverCalculator{}),
+	}
+
+	for i, obj := range objects {
+		server := newServer(ctx)
+		defer server.Stop()
+		eps, err := server.Listen(v23.GetListenSpec(ctx))
+		if err != nil {
+			t.Fatal(err)
+		}
+		root := eps[0].Name()
+		if err := server.Serve("", obj, nil); err != nil {
+			t.Fatalf("%d: %v", i, err)
+		}
+		// Synchronous calls
+		ar := arith.ArithClient(root)
+		sum, err := ar.Add(ctx, 7, 8)
+		if err != nil {
+			t.Errorf("Add: got %q but expected no error", err)
+		}
+		if sum != 15 {
+			t.Errorf("Add: expected 15 got %d", sum)
+		}
+		q, r, err := ar.DivMod(ctx, 7, 3)
+		if err != nil {
+			t.Errorf("DivMod: got %q but expected no error", err)
+		}
+		if q != 2 || r != 1 {
+			t.Errorf("DivMod: expected (2,1) got (%d,%d)", q, r)
+		}
+		diff, err := ar.Sub(ctx, base.Args{7, 8})
+		if err != nil {
+			t.Errorf("Sub: got %q but expected no error", err)
+		}
+		if diff != -1 {
+			t.Errorf("Sub: got %d, expected -1", diff)
+		}
+		prod, err := ar.Mul(ctx, base.NestedArgs{base.Args{7, 8}})
+		if err != nil {
+			t.Errorf("Mul: got %q, but expected no error", err)
+		}
+		if prod != 56 {
+			t.Errorf("Sub: got %d, expected 56", prod)
+		}
+		stream, err := ar.Count(ctx, 35)
+		if err != nil {
+			t.Fatalf("error while executing Count %v", err)
+		}
+
+		countIterator := stream.RecvStream()
+		for i := int32(0); i < 1000; i++ {
+			if !countIterator.Advance() {
+				t.Errorf("Error getting value %v", countIterator.Err())
+			}
+			val := countIterator.Value()
+			if val != 35+i {
+				t.Errorf("Expected value %d, got %d", 35+i, val)
+			}
+		}
+		if countIterator.Advance() || countIterator.Err() != nil {
+			t.Errorf("Reply stream should have been closed %v", countIterator.Err())
+		}
+
+		if err := stream.Finish(); err != nil {
+			t.Errorf("Count failed with %v", err)
+		}
+
+		addStream, err := ar.StreamingAdd(ctx)
+
+		go func() {
+			sender := addStream.SendStream()
+			for i := int32(0); i < 100; i++ {
+				if err := sender.Send(i); err != nil {
+					t.Errorf("Send error %v", err)
+				}
+			}
+			if err := sender.Close(); err != nil {
+				t.Errorf("Close error %v", err)
+			}
+		}()
+
+		var expectedSum int32
+		rStream := addStream.RecvStream()
+		for i := int32(0); i < 100; i++ {
+			expectedSum += i
+			if !rStream.Advance() {
+				t.Errorf("Error getting value %v", rStream.Err())
+			}
+			value := rStream.Value()
+			if value != expectedSum {
+				t.Errorf("Got %d but expected %d", value, expectedSum)
+			}
+		}
+
+		if rStream.Advance() || rStream.Err() != nil {
+			t.Errorf("Reply stream should have been closed %v", rStream.Err())
+		}
+
+		total, err := addStream.Finish()
+
+		if err != nil {
+			t.Errorf("Count failed with %v", err)
+		}
+
+		if total != expectedSum {
+			t.Errorf("Got %d but expexted %d", total, expectedSum)
+		}
+
+		if err := ar.GenError(ctx); err == nil {
+			t.Errorf("GenError: got %v but expected %v", err, generatedError)
+		}
+
+		// Server-side stubs
+
+		serverStub := arith.ArithServer(&serverArith{})
+		expectDesc(t, serverStub.Describe__(), []ipc.InterfaceDesc{
+			{
+				Name:    "Arith",
+				PkgPath: "v.io/x/ref/lib/vdl/testdata/arith",
+				Methods: []ipc.MethodDesc{
+					{
+						Name:    "Add",
+						InArgs:  []ipc.ArgDesc{{Name: "a"}, {Name: "b"}},
+						OutArgs: []ipc.ArgDesc{{}},
+					},
+					{
+						Name:    "DivMod",
+						InArgs:  []ipc.ArgDesc{{Name: "a"}, {Name: "b"}},
+						OutArgs: []ipc.ArgDesc{{Name: "quot"}, {Name: "rem"}},
+					},
+					{
+						Name:    "Sub",
+						InArgs:  []ipc.ArgDesc{{Name: "args"}},
+						OutArgs: []ipc.ArgDesc{{}},
+					},
+					{
+						Name:    "Mul",
+						InArgs:  []ipc.ArgDesc{{Name: "nested"}},
+						OutArgs: []ipc.ArgDesc{{}},
+					},
+					{
+						Name: "GenError",
+						Tags: []*vdl.Value{vdl.StringValue("foo"), vdl.StringValue("barz"), vdl.StringValue("hello"), vdl.Int32Value(129), vdl.Uint64Value(0x24)},
+					},
+					{
+						Name:   "Count",
+						InArgs: []ipc.ArgDesc{{Name: "start"}},
+					},
+					{
+						Name:    "StreamingAdd",
+						OutArgs: []ipc.ArgDesc{{Name: "total"}},
+					},
+					{
+						Name:    "QuoteAny",
+						InArgs:  []ipc.ArgDesc{{Name: "a"}},
+						OutArgs: []ipc.ArgDesc{{}},
+					},
+				},
+			},
+		})
+	}
+}
+
+func expectDesc(t *testing.T, got, want []ipc.InterfaceDesc) {
+	stripDesc(got)
+	stripDesc(want)
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Describe__ got %#v, want %#v", got, want)
+	}
+}
+
+func stripDesc(desc []ipc.InterfaceDesc) {
+	// Don't bother testing the documentation, to avoid spurious changes.
+	for i := range desc {
+		desc[i].Doc = ""
+		for j := range desc[i].Embeds {
+			desc[i].Embeds[j].Doc = ""
+		}
+		for j := range desc[i].Methods {
+			desc[i].Methods[j].Doc = ""
+			for k := range desc[i].Methods[j].InArgs {
+				desc[i].Methods[j].InArgs[k].Doc = ""
+			}
+			for k := range desc[i].Methods[j].OutArgs {
+				desc[i].Methods[j].OutArgs[k].Doc = ""
+			}
+			desc[i].Methods[j].InStream.Doc = ""
+			desc[i].Methods[j].OutStream.Doc = ""
+		}
+	}
+}
diff --git a/cmd/vdl/doc.go b/cmd/vdl/doc.go
new file mode 100644
index 0000000..e4831a0
--- /dev/null
+++ b/cmd/vdl/doc.go
@@ -0,0 +1,279 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+
+/*
+The vdl tool manages veyron VDL source code.  It's similar to the go tool used
+for managing Go source code.
+
+Usage:
+   vdl [flags] <command>
+
+The vdl commands are:
+   generate    Compile packages and dependencies, and generate code
+   compile     Compile packages and dependencies, but don't generate code
+   audit       Check if any packages are stale and need generation
+   list        List package and dependency info in transitive order
+   help        Display help for commands or topics
+Run "vdl help [command]" for command usage.
+
+The vdl additional help topics are:
+   packages    Description of package lists
+   vdlpath     Description of VDLPATH environment variable
+   vdlroot     Description of VDLROOT environment variable
+   vdl.config  Description of vdl.config files
+Run "vdl help [topic]" for topic details.
+
+The vdl flags are:
+ -exts=.vdl
+   Comma-separated list of valid VDL file name extensions.
+ -ignore_unknown=false
+   Ignore unknown packages provided on the command line.
+ -max_errors=-1
+   Stop processing after this many errors, or -1 for unlimited.
+ -v=false
+   Turn on verbose logging.
+ -vdl.config=vdl.config
+   Basename of the optional per-package config file.
+
+Vdl Generate
+
+Generate compiles packages and their transitive dependencies, and generates code
+in the specified languages.
+
+Usage:
+   vdl generate [flags] <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+For more information, run "vdl help packages".
+
+The vdl generate flags are:
+ -go_out_dir=
+   Go output directory.  There are three modes:
+      ""                     : Generate output in-place in the source tree
+      "dir"                  : Generate output rooted at dir
+      "src->dst[,s2->d2...]" : Generate output using translation rules
+   Assume your source tree is organized as follows:
+      VDLPATH=/home/vdl
+         /home/vdl/src/veyron/test_base/base1.vdl
+         /home/vdl/src/veyron/test_base/base2.vdl
+   Here's example output under the different modes:
+      --go_out_dir=""
+         /home/vdl/src/veyron/test_base/base1.vdl.go
+         /home/vdl/src/veyron/test_base/base2.vdl.go
+      --go_out_dir="/tmp/foo"
+         /tmp/foo/veyron/test_base/base1.vdl.go
+         /tmp/foo/veyron/test_base/base2.vdl.go
+      --go_out_dir="vdl/src->foo/bar/src"
+         /home/foo/bar/src/veyron/test_base/base1.vdl.go
+         /home/foo/bar/src/veyron/test_base/base2.vdl.go
+   When the src->dst form is used, src must match the suffix of the path just
+   before the package path, and dst is the replacement for src.  Use commas to
+   separate multiple rules; the first rule matching src is used.  The special
+   dst SKIP indicates matching packages are skipped.
+ -java_out_dir=go/src->java/src/vdl/java
+   Same semantics as --go_out_dir but applies to java code generation.
+ -java_out_pkg=v.io->io/v
+   Java output package translation rules.  Must be of the form:
+      "src->dst[,s2->d2...]"
+   If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+   commas to separate multiple rules; the first rule matching src is used, and
+   if there are no matching rules, the package remains unchanged.  The special
+   dst SKIP indicates matching packages are skipped.
+ -js_out_dir=release/go/src->release/javascript/core/src,roadmap/go/src->release/javascript/core/src,third_party/go/src->SKIP,tools/go/src->SKIP,release/go/src/v.io/v23/vdlroot->SKIP
+   Same semantics as --go_out_dir but applies to js code generation.
+ -js_relative_path_to_core=
+   If set, this is the relative path from js_out_dir to the root of the JS core
+ -lang=Go,Java
+   Comma-separated list of languages to generate, currently supporting
+   Go,Java,Javascript
+ -status=true
+   Show package names as they are updated
+
+Vdl Compile
+
+Compile compiles packages and their transitive dependencies, but does not
+generate code.  This is useful to sanity-check that your VDL files are valid.
+
+Usage:
+   vdl compile [flags] <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+For more information, run "vdl help packages".
+
+The vdl compile flags are:
+ -status=true
+   Show package names while we compile
+
+Vdl Audit
+
+Audit runs the same logic as generate, but doesn't write out generated files.
+Returns a 0 exit code if all packages are up-to-date, otherwise returns a non-0
+exit code indicating some packages need generation.
+
+Usage:
+   vdl audit [flags] <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+For more information, run "vdl help packages".
+
+The vdl audit flags are:
+ -go_out_dir=
+   Go output directory.  There are three modes:
+      ""                     : Generate output in-place in the source tree
+      "dir"                  : Generate output rooted at dir
+      "src->dst[,s2->d2...]" : Generate output using translation rules
+   Assume your source tree is organized as follows:
+      VDLPATH=/home/vdl
+         /home/vdl/src/veyron/test_base/base1.vdl
+         /home/vdl/src/veyron/test_base/base2.vdl
+   Here's example output under the different modes:
+      --go_out_dir=""
+         /home/vdl/src/veyron/test_base/base1.vdl.go
+         /home/vdl/src/veyron/test_base/base2.vdl.go
+      --go_out_dir="/tmp/foo"
+         /tmp/foo/veyron/test_base/base1.vdl.go
+         /tmp/foo/veyron/test_base/base2.vdl.go
+      --go_out_dir="vdl/src->foo/bar/src"
+         /home/foo/bar/src/veyron/test_base/base1.vdl.go
+         /home/foo/bar/src/veyron/test_base/base2.vdl.go
+   When the src->dst form is used, src must match the suffix of the path just
+   before the package path, and dst is the replacement for src.  Use commas to
+   separate multiple rules; the first rule matching src is used.  The special
+   dst SKIP indicates matching packages are skipped.
+ -java_out_dir=go/src->java/src/vdl/java
+   Same semantics as --go_out_dir but applies to java code generation.
+ -java_out_pkg=v.io->io/v
+   Java output package translation rules.  Must be of the form:
+      "src->dst[,s2->d2...]"
+   If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+   commas to separate multiple rules; the first rule matching src is used, and
+   if there are no matching rules, the package remains unchanged.  The special
+   dst SKIP indicates matching packages are skipped.
+ -js_out_dir=release/go/src->release/javascript/core/src,roadmap/go/src->release/javascript/core/src,third_party/go/src->SKIP,tools/go/src->SKIP,release/go/src/v.io/v23/vdlroot->SKIP
+   Same semantics as --go_out_dir but applies to js code generation.
+ -js_relative_path_to_core=
+   If set, this is the relative path from js_out_dir to the root of the JS core
+ -lang=Go,Java
+   Comma-separated list of languages to generate, currently supporting
+   Go,Java,Javascript
+ -status=true
+   Show package names as they are updated
+
+Vdl List
+
+List returns information about packages and their transitive dependencies, in
+transitive order.  This is the same order the generate and compile commands use
+for processing.  If "vdl list A" is run and A depends on B, which depends on C,
+the returned order will be C, B, A.  If multiple packages are specified the
+ordering is over all combined dependencies.
+
+Reminder: cyclic dependencies between packages are not allowed.  Cyclic
+dependencies between VDL files within the same package are also not allowed.
+This is more strict than regular Go; it makes it easier to generate code for
+other languages like C++.
+
+Usage:
+   vdl list <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+For more information, run "vdl help packages".
+
+Vdl Help
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
+Usage:
+   vdl help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The vdl help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
+
+Vdl Packages - help topic
+
+Most vdl commands apply to a list of packages:
+
+   vdl command <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+In its simplest form each package is an import path; e.g.
+   "v.io/x/ref/lib/vdl"
+
+A package that is an absolute path or that begins with a . or .. element is
+interpreted as a file system path, and denotes the package in that directory.
+
+A package is a pattern if it includes one or more "..." wildcards, each of which
+can match any string, including the empty string and strings containing slashes.
+Such a pattern expands to all packages found in VDLPATH with names matching the
+pattern.  As a special-case, x/... matches x as well as x's subdirectories.
+
+The special-case "all" is a synonym for "...", and denotes all packages found in
+VDLPATH.
+
+Import path elements and file names are not allowed to begin with "." or "_";
+such paths are ignored in wildcard matches, and return errors if specified
+explicitly.
+
+ Run "vdl help vdlpath" to see docs on VDLPATH.
+ Run "go help packages" to see the standard go package docs.
+
+Vdl Vdlpath - help topic
+
+The VDLPATH environment variable is used to resolve import statements. It must
+be set to compile and generate vdl packages.
+
+The format is a colon-separated list of directories, where each directory must
+have a "src/" directory that holds vdl source code.  The path below 'src'
+determines the import path.  If VDLPATH specifies multiple directories, imports
+are resolved by picking the first directory with a matching import name.
+
+An example:
+
+   VDPATH=/home/user/vdlA:/home/user/vdlB
+
+   /home/user/vdlA/
+      src/
+         foo/                 (import "foo" refers here)
+            foo1.vdl
+   /home/user/vdlB/
+      src/
+         foo/                 (this package is ignored)
+            foo2.vdl
+         bar/
+            baz/              (import "bar/baz" refers here)
+               baz.vdl
+
+Vdl Vdlroot - help topic
+
+The VDLROOT environment variable is similar to VDLPATH, but instead of pointing
+to multiple user source directories, it points at a single source directory
+containing the standard vdl packages.
+
+Setting VDLROOT is optional.
+
+If VDLROOT is empty, we try to construct it out of the VANADIUM_ROOT environment
+variable.  It is an error if both VDLROOT and VANADIUM_ROOT are empty.
+
+Vdl Vdl.Config - help topic
+
+Each vdl source package P may contain an optional file "vdl.config" within the P
+directory.  This file specifies additional configuration for the vdl tool.
+
+The format of this file is described by the vdltool.Config type in the "vdltool"
+standard package, located at VDLROOT/vdltool/config.vdl.
+
+If the file does not exist, we use the zero value of vdl.Config.
+*/
+package main
diff --git a/cmd/vdl/main.go b/cmd/vdl/main.go
new file mode 100644
index 0000000..bcd20ee
--- /dev/null
+++ b/cmd/vdl/main.go
@@ -0,0 +1,642 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"v.io/v23/vdlroot/vdltool"
+	"v.io/x/lib/cmdline"
+	"v.io/x/lib/textutil"
+	"v.io/x/ref/lib/vdl/build"
+	"v.io/x/ref/lib/vdl/codegen/golang"
+	"v.io/x/ref/lib/vdl/codegen/java"
+	"v.io/x/ref/lib/vdl/codegen/javascript"
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/vdlutil"
+)
+
+func init() {
+	log.SetFlags(log.Lshortfile | log.Ltime | log.Lmicroseconds)
+}
+
+func main() {
+	os.Exit(cmdVDL.Main())
+}
+
+func checkErrors(errs *vdlutil.Errors) error {
+	if errs.IsEmpty() {
+		return nil
+	}
+	return fmt.Errorf(`
+%s   (run with "vdl -v" for verbose logging or "vdl help" for help)`, errs)
+}
+
+// runHelper returns a function that generates a sorted list of transitive
+// targets, and calls the supplied run function.
+func runHelper(run func(targets []*build.Package, env *compile.Env)) func(cmd *cmdline.Command, args []string) error {
+	return func(cmd *cmdline.Command, args []string) error {
+		if flagVerbose {
+			vdlutil.SetVerbose()
+		}
+		if len(args) == 0 {
+			// If the user doesn't specify any targets, the cwd is implied.
+			args = append(args, ".")
+		}
+		env := compile.NewEnv(flagMaxErrors)
+		env.DisallowPathQualifiers()
+		mode := build.UnknownPathIsError
+		if flagIgnoreUnknown {
+			mode = build.UnknownPathIsIgnored
+		}
+		var opts build.Opts
+		opts.Extensions = strings.Split(flagExts, ",")
+		opts.VDLConfigName = flagVDLConfig
+		targets := build.TransitivePackages(args, mode, opts, env.Errors)
+		if err := checkErrors(env.Errors); err != nil {
+			return err
+		}
+		run(targets, env)
+		return checkErrors(env.Errors)
+	}
+}
+
+var topicPackages = cmdline.Topic{
+	Name:  "packages",
+	Short: "Description of package lists",
+	Long: `
+Most vdl commands apply to a list of packages:
+
+   vdl command <packages>
+
+<packages> are a list of packages to process, similar to the standard go tool.
+In its simplest form each package is an import path; e.g.
+   "v.io/x/ref/lib/vdl"
+
+A package that is an absolute path or that begins with a . or .. element is
+interpreted as a file system path, and denotes the package in that directory.
+
+A package is a pattern if it includes one or more "..." wildcards, each of which
+can match any string, including the empty string and strings containing
+slashes.  Such a pattern expands to all packages found in VDLPATH with names
+matching the pattern.  As a special-case, x/... matches x as well as x's
+subdirectories.
+
+The special-case "all" is a synonym for "...", and denotes all packages found
+in VDLPATH.
+
+Import path elements and file names are not allowed to begin with "." or "_";
+such paths are ignored in wildcard matches, and return errors if specified
+explicitly.
+
+ Run "vdl help vdlpath" to see docs on VDLPATH.
+ Run "go help packages" to see the standard go package docs.
+`,
+}
+
+var topicVdlPath = cmdline.Topic{
+	Name:  "vdlpath",
+	Short: "Description of VDLPATH environment variable",
+	Long: `
+The VDLPATH environment variable is used to resolve import statements.
+It must be set to compile and generate vdl packages.
+
+The format is a colon-separated list of directories, where each directory must
+have a "src/" directory that holds vdl source code.  The path below 'src'
+determines the import path.  If VDLPATH specifies multiple directories, imports
+are resolved by picking the first directory with a matching import name.
+
+An example:
+
+   VDPATH=/home/user/vdlA:/home/user/vdlB
+
+   /home/user/vdlA/
+      src/
+         foo/                 (import "foo" refers here)
+            foo1.vdl
+   /home/user/vdlB/
+      src/
+         foo/                 (this package is ignored)
+            foo2.vdl
+         bar/
+            baz/              (import "bar/baz" refers here)
+               baz.vdl
+`,
+}
+
+var topicVdlRoot = cmdline.Topic{
+	Name:  "vdlroot",
+	Short: "Description of VDLROOT environment variable",
+	Long: `
+The VDLROOT environment variable is similar to VDLPATH, but instead of pointing
+to multiple user source directories, it points at a single source directory
+containing the standard vdl packages.
+
+Setting VDLROOT is optional.
+
+If VDLROOT is empty, we try to construct it out of the VANADIUM_ROOT environment
+variable.  It is an error if both VDLROOT and VANADIUM_ROOT are empty.
+`,
+}
+
+var topicVdlConfig = cmdline.Topic{
+	Name:  "vdl.config",
+	Short: "Description of vdl.config files",
+	Long: `
+Each vdl source package P may contain an optional file "vdl.config" within the P
+directory.  This file specifies additional configuration for the vdl tool.
+
+The format of this file is described by the vdltool.Config type in the "vdltool"
+standard package, located at VDLROOT/vdltool/config.vdl.
+
+If the file does not exist, we use the zero value of vdl.Config.
+`,
+}
+
+const pkgArgName = "<packages>"
+const pkgArgLong = `
+<packages> are a list of packages to process, similar to the standard go tool.
+For more information, run "vdl help packages".
+`
+
+var cmdCompile = &cmdline.Command{
+	Run:   runHelper(runCompile),
+	Name:  "compile",
+	Short: "Compile packages and dependencies, but don't generate code",
+	Long: `
+Compile compiles packages and their transitive dependencies, but does not
+generate code.  This is useful to sanity-check that your VDL files are valid.
+`,
+	ArgsName: pkgArgName,
+	ArgsLong: pkgArgLong,
+}
+
+var cmdGenerate = &cmdline.Command{
+	Run:   runHelper(runGenerate),
+	Name:  "generate",
+	Short: "Compile packages and dependencies, and generate code",
+	Long: `
+Generate compiles packages and their transitive dependencies, and generates code
+in the specified languages.
+`,
+	ArgsName: pkgArgName,
+	ArgsLong: pkgArgLong,
+}
+
+var cmdAudit = &cmdline.Command{
+	Run:   runHelper(runAudit),
+	Name:  "audit",
+	Short: "Check if any packages are stale and need generation",
+	Long: `
+Audit runs the same logic as generate, but doesn't write out generated files.
+Returns a 0 exit code if all packages are up-to-date, otherwise returns a
+non-0 exit code indicating some packages need generation.
+`,
+	ArgsName: pkgArgName,
+	ArgsLong: pkgArgLong,
+}
+
+var cmdList = &cmdline.Command{
+	Run:   runHelper(runList),
+	Name:  "list",
+	Short: "List package and dependency info in transitive order",
+	Long: `
+List returns information about packages and their transitive dependencies, in
+transitive order.  This is the same order the generate and compile commands use
+for processing.  If "vdl list A" is run and A depends on B, which depends on C,
+the returned order will be C, B, A.  If multiple packages are specified the
+ordering is over all combined dependencies.
+
+Reminder: cyclic dependencies between packages are not allowed.  Cyclic
+dependencies between VDL files within the same package are also not allowed.
+This is more strict than regular Go; it makes it easier to generate code for
+other languages like C++.
+`,
+	ArgsName: pkgArgName,
+	ArgsLong: pkgArgLong,
+}
+
+var genLangAll = genLangs(vdltool.GenLanguageAll)
+
+type genLangs []vdltool.GenLanguage
+
+func (gls genLangs) String() string {
+	var ret string
+	for i, gl := range gls {
+		if i > 0 {
+			ret += ","
+		}
+		ret += gl.String()
+	}
+	return ret
+}
+
+func (gls *genLangs) Set(value string) error {
+	// If the flag is repeated on the cmdline it is overridden.  Duplicates within
+	// the comma separated list are ignored, and retain their original ordering.
+	*gls = genLangs{}
+	seen := make(map[vdltool.GenLanguage]bool)
+	for _, str := range strings.Split(value, ",") {
+		gl, err := vdltool.GenLanguageFromString(str)
+		if err != nil {
+			return err
+		}
+		if !seen[gl] {
+			seen[gl] = true
+			*gls = append(*gls, gl)
+		}
+	}
+	return nil
+}
+
+// genOutDir has three modes:
+//   1) If dir is non-empty, we use it as the out dir.
+//   2) If rules is non-empty, we translate using the xlate rules.
+//   3) If everything is empty, we generate in-place.
+type genOutDir struct {
+	dir   string
+	rules xlateRules
+}
+
+// xlateSrcDst specifies a translation rule, where src must match the suffix of
+// the path just before the package path, and dst is the replacement for src.
+// If dst is the special string "SKIP" we'll skip generation of packages
+// matching the src.
+type xlateSrcDst struct {
+	src, dst string
+}
+
+// xlateRules specifies a collection of translation rules.
+type xlateRules []xlateSrcDst
+
+func (x *xlateRules) String() (ret string) {
+	for _, srcdst := range *x {
+		if len(ret) > 0 {
+			ret += ","
+		}
+		ret += srcdst.src + "->" + srcdst.dst
+	}
+	return
+}
+
+func (x *xlateRules) Set(value string) error {
+	for _, rule := range strings.Split(value, ",") {
+		srcdst := strings.Split(rule, "->")
+		if len(srcdst) != 2 {
+			return fmt.Errorf("invalid out dir xlate rule %q (not src->dst format)", rule)
+		}
+		*x = append(*x, xlateSrcDst{srcdst[0], srcdst[1]})
+	}
+	return nil
+}
+
+func (x *genOutDir) String() string {
+	if x.dir != "" {
+		return x.dir
+	}
+	return x.rules.String()
+}
+
+func (x *genOutDir) Set(value string) error {
+	if strings.Contains(value, "->") {
+		x.dir = ""
+		return x.rules.Set(value)
+	}
+	x.dir = value
+	return nil
+}
+
+var (
+	// Common flags for the tool itself, applicable to all commands.
+	flagVerbose       bool
+	flagMaxErrors     int
+	flagExts          string
+	flagVDLConfig     string
+	flagIgnoreUnknown bool
+
+	// Options for each command.
+	optCompileStatus bool
+	optGenStatus     bool
+	optGenGoOutDir   = genOutDir{}
+	optGenJavaOutDir = genOutDir{
+		rules: xlateRules{
+			{"go/src", "java/src/vdl/java"},
+		},
+	}
+	optGenJavascriptOutDir = genOutDir{
+		rules: xlateRules{
+			{"release/go/src", "release/javascript/core/src"},
+			{"roadmap/go/src", "release/javascript/core/src"},
+			{"third_party/go/src", "SKIP"},
+			{"tools/go/src", "SKIP"},
+			// TODO(toddw): Skip vdlroot javascript generation for now.
+			{"release/go/src/v.io/v23/vdlroot", "SKIP"},
+		},
+	}
+	optGenJavaOutPkg = xlateRules{
+		{"v.io", "io/v"},
+	}
+	optPathToJSCore string
+	// TODO(bjornick): Add javascript to the default gen langs.
+	optGenLangs = genLangs{vdltool.GenLanguageGo, vdltool.GenLanguageJava}
+)
+
+// Root returns the root command for the VDL tool.
+var cmdVDL = &cmdline.Command{
+	Name:  "vdl",
+	Short: "Manage veyron VDL source code",
+	Long: `
+The vdl tool manages veyron VDL source code.  It's similar to the go tool used
+for managing Go source code.
+`,
+	Children: []*cmdline.Command{cmdGenerate, cmdCompile, cmdAudit, cmdList},
+	Topics:   []cmdline.Topic{topicPackages, topicVdlPath, topicVdlRoot, topicVdlConfig},
+}
+
+func init() {
+	// Common flags for the tool itself, applicable to all commands.
+	cmdVDL.Flags.BoolVar(&flagVerbose, "v", false, "Turn on verbose logging.")
+	cmdVDL.Flags.IntVar(&flagMaxErrors, "max_errors", -1, "Stop processing after this many errors, or -1 for unlimited.")
+	cmdVDL.Flags.StringVar(&flagExts, "exts", ".vdl", "Comma-separated list of valid VDL file name extensions.")
+	cmdVDL.Flags.StringVar(&flagVDLConfig, "vdl.config", "vdl.config", "Basename of the optional per-package config file.")
+	cmdVDL.Flags.BoolVar(&flagIgnoreUnknown, "ignore_unknown", false, "Ignore unknown packages provided on the command line.")
+
+	// Options for compile.
+	cmdCompile.Flags.BoolVar(&optCompileStatus, "status", true, "Show package names while we compile")
+
+	// Options for generate.
+	cmdGenerate.Flags.Var(&optGenLangs, "lang", "Comma-separated list of languages to generate, currently supporting "+genLangAll.String())
+	cmdGenerate.Flags.BoolVar(&optGenStatus, "status", true, "Show package names as they are updated")
+	// TODO(toddw): Move out_dir configuration into vdl.config, and provide a
+	// generic override mechanism for vdl.config.
+	cmdGenerate.Flags.Var(&optGenGoOutDir, "go_out_dir", `
+Go output directory.  There are three modes:
+   ""                     : Generate output in-place in the source tree
+   "dir"                  : Generate output rooted at dir
+   "src->dst[,s2->d2...]" : Generate output using translation rules
+Assume your source tree is organized as follows:
+   VDLPATH=/home/vdl
+      /home/vdl/src/veyron/test_base/base1.vdl
+      /home/vdl/src/veyron/test_base/base2.vdl
+Here's example output under the different modes:
+   --go_out_dir=""
+      /home/vdl/src/veyron/test_base/base1.vdl.go
+      /home/vdl/src/veyron/test_base/base2.vdl.go
+   --go_out_dir="/tmp/foo"
+      /tmp/foo/veyron/test_base/base1.vdl.go
+      /tmp/foo/veyron/test_base/base2.vdl.go
+   --go_out_dir="vdl/src->foo/bar/src"
+      /home/foo/bar/src/veyron/test_base/base1.vdl.go
+      /home/foo/bar/src/veyron/test_base/base2.vdl.go
+When the src->dst form is used, src must match the suffix of the path just
+before the package path, and dst is the replacement for src.  Use commas to
+separate multiple rules; the first rule matching src is used.  The special dst
+SKIP indicates matching packages are skipped.`)
+	cmdGenerate.Flags.Var(&optGenJavaOutDir, "java_out_dir",
+		"Same semantics as --go_out_dir but applies to java code generation.")
+	cmdGenerate.Flags.Var(&optGenJavaOutPkg, "java_out_pkg", `
+Java output package translation rules.  Must be of the form:
+   "src->dst[,s2->d2...]"
+If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+commas to separate multiple rules; the first rule matching src is used, and if
+there are no matching rules, the package remains unchanged.  The special dst
+SKIP indicates matching packages are skipped.`)
+	cmdGenerate.Flags.Var(&optGenJavascriptOutDir, "js_out_dir",
+		"Same semantics as --go_out_dir but applies to js code generation.")
+	cmdGenerate.Flags.StringVar(&optPathToJSCore, "js_relative_path_to_core", "",
+		"If set, this is the relative path from js_out_dir to the root of the JS core")
+
+	// Options for audit are identical to generate.
+	cmdAudit.Flags = cmdGenerate.Flags
+}
+
+func runCompile(targets []*build.Package, env *compile.Env) {
+	for _, target := range targets {
+		pkg := build.BuildPackage(target, env)
+		if pkg != nil && optCompileStatus {
+			fmt.Println(pkg.Path)
+		}
+	}
+}
+
+func runGenerate(targets []*build.Package, env *compile.Env) {
+	gen(false, targets, env)
+}
+
+func runAudit(targets []*build.Package, env *compile.Env) {
+	if gen(true, targets, env) && env.Errors.IsEmpty() {
+		// Some packages are stale, and there were no errors; return an arbitrary
+		// non-0 exit code.  Errors are handled in runHelper, as usual.
+		os.Exit(10)
+	}
+}
+
+func shouldGenerate(config vdltool.Config, lang vdltool.GenLanguage) bool {
+	// If config.GenLanguages is empty, all languages are allowed to be generated.
+	_, ok := config.GenLanguages[lang]
+	return len(config.GenLanguages) == 0 || ok
+}
+
+// gen generates the given targets with env.  If audit is true, only checks
+// whether any packages are stale; otherwise files will actually be written out.
+// Returns true if any packages are stale.
+func gen(audit bool, targets []*build.Package, env *compile.Env) bool {
+	anychanged := false
+	for _, target := range targets {
+		pkg := build.BuildPackage(target, env)
+		if pkg == nil {
+			// Stop at the first package that fails to compile.
+			if env.Errors.IsEmpty() {
+				env.Errors.Errorf("%s: internal error (compiled into nil package)", target.Path)
+			}
+			return true
+		}
+		// TODO(toddw): Skip code generation if the semantic contents of the
+		// generated file haven't changed.
+		pkgchanged := false
+		for _, gl := range optGenLangs {
+			switch gl {
+			case vdltool.GenLanguageGo:
+				if !shouldGenerate(pkg.Config, vdltool.GenLanguageGo) {
+					continue
+				}
+				dir, err := xlateOutDir(target.Dir, target.GenPath, optGenGoOutDir, pkg.GenPath)
+				if handleErrorOrSkip("--go_out_dir", err, env) {
+					continue
+				}
+				for _, file := range pkg.Files {
+					data := golang.Generate(file, env)
+					if writeFile(audit, data, dir, file.BaseName+".go", env) {
+						pkgchanged = true
+					}
+				}
+			case vdltool.GenLanguageJava:
+				if !shouldGenerate(pkg.Config, vdltool.GenLanguageJava) {
+					continue
+				}
+				pkgPath, err := xlatePkgPath(pkg.GenPath, optGenJavaOutPkg)
+				if handleErrorOrSkip("--java_out_pkg", err, env) {
+					continue
+				}
+				dir, err := xlateOutDir(target.Dir, target.GenPath, optGenJavaOutDir, pkgPath)
+				if handleErrorOrSkip("--java_out_dir", err, env) {
+					continue
+				}
+				java.SetPkgPathXlator(func(pkgPath string) string {
+					result, _ := xlatePkgPath(pkgPath, optGenJavaOutPkg)
+					return result
+				})
+				for _, file := range java.Generate(pkg, env) {
+					fileDir := filepath.Join(dir, file.Dir)
+					if writeFile(audit, file.Data, fileDir, file.Name, env) {
+						pkgchanged = true
+					}
+				}
+			case vdltool.GenLanguageJavascript:
+				if !shouldGenerate(pkg.Config, vdltool.GenLanguageJavascript) {
+					continue
+				}
+				dir, err := xlateOutDir(target.Dir, target.GenPath, optGenJavascriptOutDir, pkg.GenPath)
+				if handleErrorOrSkip("--js_out_dir", err, env) {
+					continue
+				}
+				path := func(importPath string) string {
+					prefix := filepath.Clean(target.Dir[0 : len(target.Dir)-len(target.GenPath)])
+					pkgDir := filepath.Join(prefix, filepath.FromSlash(importPath))
+					fullDir, err := xlateOutDir(pkgDir, importPath, optGenJavascriptOutDir, importPath)
+					if err != nil {
+						panic(err)
+					}
+					cleanPath, err := filepath.Rel(dir, fullDir)
+					if err != nil {
+						panic(err)
+					}
+					return cleanPath
+				}
+				data := javascript.Generate(pkg, env, path, optPathToJSCore)
+				if writeFile(audit, data, dir, "index.js", env) {
+					pkgchanged = true
+				}
+			default:
+				env.Errors.Errorf("Generating code for language %v isn't supported", gl)
+			}
+		}
+		if pkgchanged {
+			anychanged = true
+			if optGenStatus {
+				fmt.Println(pkg.Path)
+			}
+		}
+	}
+	return anychanged
+}
+
+// writeFile writes data into the standard location for file, using the given
+// suffix.  Errors are reported via env.  Returns true iff the file doesn't
+// already exist with the given data.
+func writeFile(audit bool, data []byte, dirName, baseName string, env *compile.Env) bool {
+	dstName := filepath.Join(dirName, baseName)
+	// Don't change anything if old and new are the same.
+	if oldData, err := ioutil.ReadFile(dstName); err == nil && bytes.Equal(oldData, data) {
+		return false
+	}
+	if !audit {
+		// Create containing directory, if it doesn't already exist.
+		if err := os.MkdirAll(dirName, os.FileMode(0777)); err != nil {
+			env.Errors.Errorf("Couldn't create directory %s: %v", dirName, err)
+			return true
+		}
+		if err := ioutil.WriteFile(dstName, data, os.FileMode(0666)); err != nil {
+			env.Errors.Errorf("Couldn't write file %s: %v", dstName, err)
+			return true
+		}
+	}
+	return true
+}
+
+func handleErrorOrSkip(prefix string, err error, env *compile.Env) bool {
+	if err != nil {
+		if err != errSkip {
+			env.Errors.Errorf("%s error: %v", prefix, err)
+		}
+		return true
+	}
+	return false
+}
+
+var errSkip = fmt.Errorf("SKIP")
+
+func xlateOutDir(dir, path string, outdir genOutDir, outPkgPath string) (string, error) {
+	path = filepath.FromSlash(path)
+	outPkgPath = filepath.FromSlash(outPkgPath)
+	// Strip package path from the directory.
+	if !strings.HasSuffix(dir, path) {
+		return "", fmt.Errorf("package dir %q doesn't end with package path %q", dir, path)
+	}
+	dir = filepath.Clean(dir[:len(dir)-len(path)])
+
+	switch {
+	case outdir.dir != "":
+		return filepath.Join(outdir.dir, outPkgPath), nil
+	case len(outdir.rules) == 0:
+		return filepath.Join(dir, outPkgPath), nil
+	}
+	// Try translation rules in order.
+	for _, xlate := range outdir.rules {
+		d := dir
+		if !strings.HasSuffix(d, xlate.src) {
+			continue
+		}
+		if xlate.dst == "SKIP" {
+			return "", errSkip
+		}
+		d = filepath.Clean(d[:len(d)-len(xlate.src)])
+		return filepath.Join(d, xlate.dst, outPkgPath), nil
+	}
+	return "", fmt.Errorf("package prefix %q doesn't match translation rules %q", dir, outdir)
+}
+
+func xlatePkgPath(pkgPath string, rules xlateRules) (string, error) {
+	for _, xlate := range rules {
+		if !strings.HasPrefix(pkgPath, xlate.src) {
+			continue
+		}
+		if xlate.dst == "SKIP" {
+			return pkgPath, errSkip
+		}
+		return xlate.dst + pkgPath[len(xlate.src):], nil
+	}
+	return pkgPath, nil
+}
+
+func runList(targets []*build.Package, env *compile.Env) {
+	for tx, target := range targets {
+		num := fmt.Sprintf("%d", tx)
+		fmt.Printf("%s %s\n", num, strings.Repeat("=", termWidth()-len(num)-1))
+		fmt.Printf("Name:    %v\n", target.Name)
+		fmt.Printf("Config:  %+v\n", target.Config)
+		fmt.Printf("Path:    %v\n", target.Path)
+		fmt.Printf("GenPath: %v\n", target.GenPath)
+		fmt.Printf("Dir:     %v\n", target.Dir)
+		if len(target.BaseFileNames) > 0 {
+			fmt.Print("Files:\n")
+			for _, file := range target.BaseFileNames {
+				fmt.Printf("   %v\n", file)
+			}
+		}
+	}
+}
+
+func termWidth() int {
+	if _, width, err := textutil.TerminalSize(); err == nil && width > 0 {
+		return width
+	}
+	return 80 // have a reasonable default
+}
diff --git a/cmd/vdl/vdl_test.go b/cmd/vdl/vdl_test.go
new file mode 100644
index 0000000..93b2f9d
--- /dev/null
+++ b/cmd/vdl/vdl_test.go
@@ -0,0 +1,61 @@
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+const (
+	testDir    = "../../lib/vdl/testdata/base"
+	outPkgPath = "v.io/x/ref/lib/vdl/testdata/base"
+)
+
+// Compares generated VDL files against the copy in the repo.
+func TestVDLGenerator(t *testing.T) {
+	// Setup the vdl command-line.
+	cmdVDL.Init(nil, os.Stdout, os.Stderr)
+	// Use vdl to generate Go code from input, into a temporary directory.
+	outDir, err := ioutil.TempDir("", "vdltest")
+	if err != nil {
+		t.Fatalf("TempDir() failed: %v", err)
+	}
+	defer os.RemoveAll(outDir)
+	// TODO(toddw): test the generated java and javascript files too.
+	outOpt := fmt.Sprintf("--go_out_dir=%s", outDir)
+	if err := cmdVDL.Execute([]string{"generate", "--lang=go", outOpt, testDir}); err != nil {
+		t.Fatalf("Execute() failed: %v", err)
+	}
+	// Check that each *.vdl.go file in the testDir matches the generated output.
+	entries, err := ioutil.ReadDir(testDir)
+	if err != nil {
+		t.Fatalf("ReadDir(%v) failed: %v", testDir, err)
+	}
+	numEqual := 0
+	for _, entry := range entries {
+		if !strings.HasSuffix(entry.Name(), ".vdl.go") {
+			continue
+		}
+		testFile := filepath.Join(testDir, entry.Name())
+		testBytes, err := ioutil.ReadFile(testFile)
+		if err != nil {
+			t.Fatalf("ReadFile(%v) failed: %v", testFile, err)
+		}
+		outFile := filepath.Join(outDir, outPkgPath, entry.Name())
+		outBytes, err := ioutil.ReadFile(outFile)
+		if err != nil {
+			t.Fatalf("ReadFile(%v) failed: %v", outFile, err)
+		}
+		if !bytes.Equal(outBytes, testBytes) {
+			t.Fatalf("GOT:\n%v\n\nWANT:\n%v\n", string(outBytes), string(testBytes))
+		}
+		numEqual++
+	}
+	if numEqual == 0 {
+		t.Fatalf("testDir %s has no golden files *.vdl.go", testDir)
+	}
+}
diff --git a/tools/vom/doc.go b/cmd/vom/doc.go
similarity index 100%
rename from tools/vom/doc.go
rename to cmd/vom/doc.go
diff --git a/tools/vom/types.vdl b/cmd/vom/types.vdl
similarity index 100%
rename from tools/vom/types.vdl
rename to cmd/vom/types.vdl
diff --git a/tools/vom/types.vdl.go b/cmd/vom/types.vdl.go
similarity index 95%
rename from tools/vom/types.vdl.go
rename to cmd/vom/types.vdl.go
index fff5e16..4a9810c 100644
--- a/tools/vom/types.vdl.go
+++ b/cmd/vom/types.vdl.go
@@ -51,7 +51,7 @@
 }
 
 func (dataRep) __VDLReflect(struct {
-	Name string "v.io/x/ref/tools/vom.dataRep"
+	Name string "v.io/x/ref/cmd/vom.dataRep"
 	Enum struct{ Hex, Binary string }
 }) {
 }
diff --git a/tools/vom/vom.go b/cmd/vom/vom.go
similarity index 100%
rename from tools/vom/vom.go
rename to cmd/vom/vom.go
diff --git a/tools/vomtestgen/doc.go b/cmd/vomtestgen/doc.go
similarity index 100%
rename from tools/vomtestgen/doc.go
rename to cmd/vomtestgen/doc.go
diff --git a/tools/vomtestgen/generate.go b/cmd/vomtestgen/generate.go
similarity index 100%
rename from tools/vomtestgen/generate.go
rename to cmd/vomtestgen/generate.go
diff --git a/tools/vomtestgen/main.go b/cmd/vomtestgen/main.go
similarity index 100%
rename from tools/vomtestgen/main.go
rename to cmd/vomtestgen/main.go
diff --git a/cmd/vrpc/doc.go b/cmd/vrpc/doc.go
new file mode 100644
index 0000000..df0d470
--- /dev/null
+++ b/cmd/vrpc/doc.go
@@ -0,0 +1,139 @@
+// This file was auto-generated via go generate.
+// DO NOT UPDATE MANUALLY
+
+/*
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
+
+Usage:
+   vrpc <command>
+
+The vrpc commands are:
+   signature   Describe the interfaces of a Vanadium server
+   call        Call a method of a Vanadium server
+   identify    Reveal blessings presented by a Vanadium server
+   help        Display help for commands or topics
+Run "vrpc help [command]" for command usage.
+
+The global flags are:
+ -alsologtostderr=true
+   log to standard error as well as files
+ -log_backtrace_at=:0
+   when logging hits line file:N, emit a stack trace
+ -log_dir=
+   if non-empty, write log files to this directory
+ -logtostderr=false
+   log to standard error instead of files
+ -max_stack_buf_size=4292608
+   max size in bytes of the buffer to use for logging stack traces
+ -stderrthreshold=2
+   logs at or above this threshold go to stderr
+ -v=0
+   log level for V logs
+ -vanadium.i18n_catalogue=
+   18n catalogue files to load, comma separated
+ -veyron.credentials=
+   directory to use for storing security credentials
+ -veyron.namespace.root=[/ns.dev.v.io:8101]
+   local namespace root; can be repeated to provided multiple roots
+ -veyron.proxy=
+   object name of proxy service to use to export services across network
+   boundaries
+ -veyron.tcp.address=
+   address to listen on
+ -veyron.tcp.protocol=tcp
+   protocol to listen with
+ -veyron.vtrace.cache_size=1024
+   The number of vtrace traces to store in memory.
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
+   If true, dump all stored traces on runtime shutdown.
+ -veyron.vtrace.sample_rate=0
+   Rate (from 0.0 to 1.0) to sample vtrace traces.
+ -vmodule=
+   comma-separated list of pattern=N settings for file-filtered logging
+
+Vrpc Signature
+
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
+
+Usage:
+   vrpc signature <server> [method]
+
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+
+[method] is the optional server method name.
+
+Vrpc Call
+
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
+
+Usage:
+   vrpc call <server> <method> [args...]
+
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+
+<method> is the server method to call.
+
+[args...] are the positional input arguments, specified as VDL expressions.
+
+Vrpc Identify
+
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+
+Usage:
+   vrpc identify <server>
+
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+
+Vrpc Help
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+The output is formatted to a target width in runes.  The target width is
+determined by checking the environment variable CMDLINE_WIDTH, falling back on
+the terminal width from the OS, falling back on 80 chars.  By setting
+CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
+if x == 0 or is unset one of the fallbacks is used.
+
+Usage:
+   vrpc help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The vrpc help flags are:
+ -style=text
+   The formatting style for help output, either "text" or "godoc".
+*/
+package main
diff --git a/cmd/vrpc/test_base/test_base.vdl b/cmd/vrpc/test_base/test_base.vdl
new file mode 100644
index 0000000..70e3b85
--- /dev/null
+++ b/cmd/vrpc/test_base/test_base.vdl
@@ -0,0 +1,36 @@
+package test_base
+
+type Struct struct {
+  X,Y int32
+}
+
+type Array2Int [2]int32
+
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type TypeTester interface {
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
+
+	// Methods to test support for composite types.
+	XEchoArray(I1 Array2Int) (O1 Array2Int | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 Struct) (O1 Struct | error)
+
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1, I2 int32) (O1, O2 int32 | error)
+	YNoArgs() error
+
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+}
diff --git a/cmd/vrpc/test_base/test_base.vdl.go b/cmd/vrpc/test_base/test_base.vdl.go
new file mode 100644
index 0000000..c55bffd
--- /dev/null
+++ b/cmd/vrpc/test_base/test_base.vdl.go
@@ -0,0 +1,682 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: test_base.vdl
+
+package test_base
+
+import (
+	// VDL system imports
+	"io"
+	"v.io/v23"
+	"v.io/v23/context"
+	"v.io/v23/ipc"
+	"v.io/v23/vdl"
+)
+
+type Struct struct {
+	X int32
+	Y int32
+}
+
+func (Struct) __VDLReflect(struct {
+	Name string "v.io/x/ref/cmd/vrpc/test_base.Struct"
+}) {
+}
+
+type Array2Int [2]int32
+
+func (Array2Int) __VDLReflect(struct {
+	Name string "v.io/x/ref/cmd/vrpc/test_base.Array2Int"
+}) {
+}
+
+func init() {
+	vdl.Register((*Struct)(nil))
+	vdl.Register((*Array2Int)(nil))
+}
+
+// TypeTesterClientMethods is the client interface
+// containing TypeTester methods.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type TypeTesterClientMethods interface {
+	// Methods to test support for primitive types.
+	EchoBool(ctx *context.T, I1 bool, opts ...ipc.CallOpt) (O1 bool, err error)
+	EchoFloat32(ctx *context.T, I1 float32, opts ...ipc.CallOpt) (O1 float32, err error)
+	EchoFloat64(ctx *context.T, I1 float64, opts ...ipc.CallOpt) (O1 float64, err error)
+	EchoInt32(ctx *context.T, I1 int32, opts ...ipc.CallOpt) (O1 int32, err error)
+	EchoInt64(ctx *context.T, I1 int64, opts ...ipc.CallOpt) (O1 int64, err error)
+	EchoString(ctx *context.T, I1 string, opts ...ipc.CallOpt) (O1 string, err error)
+	EchoByte(ctx *context.T, I1 byte, opts ...ipc.CallOpt) (O1 byte, err error)
+	EchoUint32(ctx *context.T, I1 uint32, opts ...ipc.CallOpt) (O1 uint32, err error)
+	EchoUint64(ctx *context.T, I1 uint64, opts ...ipc.CallOpt) (O1 uint64, err error)
+	// Methods to test support for composite types.
+	XEchoArray(ctx *context.T, I1 Array2Int, opts ...ipc.CallOpt) (O1 Array2Int, err error)
+	XEchoMap(ctx *context.T, I1 map[int32]string, opts ...ipc.CallOpt) (O1 map[int32]string, err error)
+	XEchoSet(ctx *context.T, I1 map[int32]struct{}, opts ...ipc.CallOpt) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx *context.T, I1 []int32, opts ...ipc.CallOpt) (O1 []int32, err error)
+	XEchoStruct(ctx *context.T, I1 Struct, opts ...ipc.CallOpt) (O1 Struct, err error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(ctx *context.T, I1 int32, I2 int32, opts ...ipc.CallOpt) (O1 int32, O2 int32, err error)
+	YNoArgs(*context.T, ...ipc.CallOpt) error
+	// Methods to test support for streaming.
+	ZStream(ctx *context.T, NumStreamItems int32, StreamItem bool, opts ...ipc.CallOpt) (TypeTesterZStreamClientCall, error)
+}
+
+// TypeTesterClientStub adds universal methods to TypeTesterClientMethods.
+type TypeTesterClientStub interface {
+	TypeTesterClientMethods
+	ipc.UniversalServiceMethods
+}
+
+// TypeTesterClient returns a client stub for TypeTester.
+func TypeTesterClient(name string, opts ...ipc.BindOpt) TypeTesterClientStub {
+	var client ipc.Client
+	for _, opt := range opts {
+		if clientOpt, ok := opt.(ipc.Client); ok {
+			client = clientOpt
+		}
+	}
+	return implTypeTesterClientStub{name, client}
+}
+
+type implTypeTesterClientStub struct {
+	name   string
+	client ipc.Client
+}
+
+func (c implTypeTesterClientStub) c(ctx *context.T) ipc.Client {
+	if c.client != nil {
+		return c.client
+	}
+	return v23.GetClient(ctx)
+}
+
+func (c implTypeTesterClientStub) EchoBool(ctx *context.T, i0 bool, opts ...ipc.CallOpt) (o0 bool, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoBool", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoFloat32(ctx *context.T, i0 float32, opts ...ipc.CallOpt) (o0 float32, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoFloat32", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoFloat64(ctx *context.T, i0 float64, opts ...ipc.CallOpt) (o0 float64, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoFloat64", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoInt32(ctx *context.T, i0 int32, opts ...ipc.CallOpt) (o0 int32, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoInt32", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoInt64(ctx *context.T, i0 int64, opts ...ipc.CallOpt) (o0 int64, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoInt64", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoString(ctx *context.T, i0 string, opts ...ipc.CallOpt) (o0 string, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoString", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoByte(ctx *context.T, i0 byte, opts ...ipc.CallOpt) (o0 byte, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoByte", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoUint32(ctx *context.T, i0 uint32, opts ...ipc.CallOpt) (o0 uint32, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint32", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) EchoUint64(ctx *context.T, i0 uint64, opts ...ipc.CallOpt) (o0 uint64, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint64", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) XEchoArray(ctx *context.T, i0 Array2Int, opts ...ipc.CallOpt) (o0 Array2Int, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoArray", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) XEchoMap(ctx *context.T, i0 map[int32]string, opts ...ipc.CallOpt) (o0 map[int32]string, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoMap", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) XEchoSet(ctx *context.T, i0 map[int32]struct{}, opts ...ipc.CallOpt) (o0 map[int32]struct{}, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSet", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) XEchoSlice(ctx *context.T, i0 []int32, opts ...ipc.CallOpt) (o0 []int32, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSlice", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) XEchoStruct(ctx *context.T, i0 Struct, opts ...ipc.CallOpt) (o0 Struct, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoStruct", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0)
+	return
+}
+
+func (c implTypeTesterClientStub) YMultiArg(ctx *context.T, i0 int32, i1 int32, opts ...ipc.CallOpt) (o0 int32, o1 int32, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YMultiArg", []interface{}{i0, i1}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0, &o1)
+	return
+}
+
+func (c implTypeTesterClientStub) YNoArgs(ctx *context.T, opts ...ipc.CallOpt) (err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YNoArgs", nil, opts...); err != nil {
+		return
+	}
+	err = call.Finish()
+	return
+}
+
+func (c implTypeTesterClientStub) ZStream(ctx *context.T, i0 int32, i1 bool, opts ...ipc.CallOpt) (ocall TypeTesterZStreamClientCall, err error) {
+	var call ipc.ClientCall
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "ZStream", []interface{}{i0, i1}, opts...); err != nil {
+		return
+	}
+	ocall = &implTypeTesterZStreamClientCall{ClientCall: call}
+	return
+}
+
+// TypeTesterZStreamClientStream is the client stream for TypeTester.ZStream.
+type TypeTesterZStreamClientStream interface {
+	// RecvStream returns the receiver side of the TypeTester.ZStream client stream.
+	RecvStream() interface {
+		// Advance stages an item so that it may be retrieved via Value.  Returns
+		// true iff there is an item to retrieve.  Advance must be called before
+		// Value is called.  May block if an item is not available.
+		Advance() bool
+		// Value returns the item that was staged by Advance.  May panic if Advance
+		// returned false or was not called.  Never blocks.
+		Value() bool
+		// Err returns any error encountered by Advance.  Never blocks.
+		Err() error
+	}
+}
+
+// TypeTesterZStreamClientCall represents the call returned from TypeTester.ZStream.
+type TypeTesterZStreamClientCall interface {
+	TypeTesterZStreamClientStream
+	// Finish blocks until the server is done, and returns the positional return
+	// values for call.
+	//
+	// Finish returns immediately if the call has been canceled; depending on the
+	// timing the output could either be an error signaling cancelation, or the
+	// valid positional return values from the server.
+	//
+	// Calling Finish is mandatory for releasing stream resources, unless the call
+	// has been canceled or any of the other methods return an error.  Finish should
+	// be called at most once.
+	Finish() error
+}
+
+type implTypeTesterZStreamClientCall struct {
+	ipc.ClientCall
+	valRecv bool
+	errRecv error
+}
+
+func (c *implTypeTesterZStreamClientCall) RecvStream() interface {
+	Advance() bool
+	Value() bool
+	Err() error
+} {
+	return implTypeTesterZStreamCallRecv{c}
+}
+
+type implTypeTesterZStreamCallRecv struct {
+	c *implTypeTesterZStreamClientCall
+}
+
+func (c implTypeTesterZStreamCallRecv) Advance() bool {
+	c.c.errRecv = c.c.Recv(&c.c.valRecv)
+	return c.c.errRecv == nil
+}
+func (c implTypeTesterZStreamCallRecv) Value() bool {
+	return c.c.valRecv
+}
+func (c implTypeTesterZStreamCallRecv) Err() error {
+	if c.c.errRecv == io.EOF {
+		return nil
+	}
+	return c.c.errRecv
+}
+func (c *implTypeTesterZStreamClientCall) Finish() (err error) {
+	err = c.ClientCall.Finish()
+	return
+}
+
+// TypeTesterServerMethods is the interface a server writer
+// implements for TypeTester.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type TypeTesterServerMethods interface {
+	// Methods to test support for primitive types.
+	EchoBool(ctx ipc.ServerCall, I1 bool) (O1 bool, err error)
+	EchoFloat32(ctx ipc.ServerCall, I1 float32) (O1 float32, err error)
+	EchoFloat64(ctx ipc.ServerCall, I1 float64) (O1 float64, err error)
+	EchoInt32(ctx ipc.ServerCall, I1 int32) (O1 int32, err error)
+	EchoInt64(ctx ipc.ServerCall, I1 int64) (O1 int64, err error)
+	EchoString(ctx ipc.ServerCall, I1 string) (O1 string, err error)
+	EchoByte(ctx ipc.ServerCall, I1 byte) (O1 byte, err error)
+	EchoUint32(ctx ipc.ServerCall, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx ipc.ServerCall, I1 uint64) (O1 uint64, err error)
+	// Methods to test support for composite types.
+	XEchoArray(ctx ipc.ServerCall, I1 Array2Int) (O1 Array2Int, err error)
+	XEchoMap(ctx ipc.ServerCall, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx ipc.ServerCall, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx ipc.ServerCall, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx ipc.ServerCall, I1 Struct) (O1 Struct, err error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(ctx ipc.ServerCall, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(ipc.ServerCall) error
+	// Methods to test support for streaming.
+	ZStream(ctx TypeTesterZStreamContext, NumStreamItems int32, StreamItem bool) error
+}
+
+// TypeTesterServerStubMethods is the server interface containing
+// TypeTester methods, as expected by ipc.Server.
+// The only difference between this interface and TypeTesterServerMethods
+// is the streaming methods.
+type TypeTesterServerStubMethods interface {
+	// Methods to test support for primitive types.
+	EchoBool(ctx ipc.ServerCall, I1 bool) (O1 bool, err error)
+	EchoFloat32(ctx ipc.ServerCall, I1 float32) (O1 float32, err error)
+	EchoFloat64(ctx ipc.ServerCall, I1 float64) (O1 float64, err error)
+	EchoInt32(ctx ipc.ServerCall, I1 int32) (O1 int32, err error)
+	EchoInt64(ctx ipc.ServerCall, I1 int64) (O1 int64, err error)
+	EchoString(ctx ipc.ServerCall, I1 string) (O1 string, err error)
+	EchoByte(ctx ipc.ServerCall, I1 byte) (O1 byte, err error)
+	EchoUint32(ctx ipc.ServerCall, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx ipc.ServerCall, I1 uint64) (O1 uint64, err error)
+	// Methods to test support for composite types.
+	XEchoArray(ctx ipc.ServerCall, I1 Array2Int) (O1 Array2Int, err error)
+	XEchoMap(ctx ipc.ServerCall, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx ipc.ServerCall, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx ipc.ServerCall, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx ipc.ServerCall, I1 Struct) (O1 Struct, err error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(ctx ipc.ServerCall, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(ipc.ServerCall) error
+	// Methods to test support for streaming.
+	ZStream(ctx *TypeTesterZStreamContextStub, NumStreamItems int32, StreamItem bool) error
+}
+
+// TypeTesterServerStub adds universal methods to TypeTesterServerStubMethods.
+type TypeTesterServerStub interface {
+	TypeTesterServerStubMethods
+	// Describe the TypeTester interfaces.
+	Describe__() []ipc.InterfaceDesc
+}
+
+// TypeTesterServer returns a server stub for TypeTester.
+// It converts an implementation of TypeTesterServerMethods into
+// an object that may be used by ipc.Server.
+func TypeTesterServer(impl TypeTesterServerMethods) TypeTesterServerStub {
+	stub := implTypeTesterServerStub{
+		impl: impl,
+	}
+	// Initialize GlobState; always check the stub itself first, to handle the
+	// case where the user has the Glob method defined in their VDL source.
+	if gs := ipc.NewGlobState(stub); gs != nil {
+		stub.gs = gs
+	} else if gs := ipc.NewGlobState(impl); gs != nil {
+		stub.gs = gs
+	}
+	return stub
+}
+
+type implTypeTesterServerStub struct {
+	impl TypeTesterServerMethods
+	gs   *ipc.GlobState
+}
+
+func (s implTypeTesterServerStub) EchoBool(ctx ipc.ServerCall, i0 bool) (bool, error) {
+	return s.impl.EchoBool(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoFloat32(ctx ipc.ServerCall, i0 float32) (float32, error) {
+	return s.impl.EchoFloat32(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoFloat64(ctx ipc.ServerCall, i0 float64) (float64, error) {
+	return s.impl.EchoFloat64(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoInt32(ctx ipc.ServerCall, i0 int32) (int32, error) {
+	return s.impl.EchoInt32(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoInt64(ctx ipc.ServerCall, i0 int64) (int64, error) {
+	return s.impl.EchoInt64(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoString(ctx ipc.ServerCall, i0 string) (string, error) {
+	return s.impl.EchoString(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoByte(ctx ipc.ServerCall, i0 byte) (byte, error) {
+	return s.impl.EchoByte(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoUint32(ctx ipc.ServerCall, i0 uint32) (uint32, error) {
+	return s.impl.EchoUint32(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) EchoUint64(ctx ipc.ServerCall, i0 uint64) (uint64, error) {
+	return s.impl.EchoUint64(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) XEchoArray(ctx ipc.ServerCall, i0 Array2Int) (Array2Int, error) {
+	return s.impl.XEchoArray(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) XEchoMap(ctx ipc.ServerCall, i0 map[int32]string) (map[int32]string, error) {
+	return s.impl.XEchoMap(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) XEchoSet(ctx ipc.ServerCall, i0 map[int32]struct{}) (map[int32]struct{}, error) {
+	return s.impl.XEchoSet(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) XEchoSlice(ctx ipc.ServerCall, i0 []int32) ([]int32, error) {
+	return s.impl.XEchoSlice(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) XEchoStruct(ctx ipc.ServerCall, i0 Struct) (Struct, error) {
+	return s.impl.XEchoStruct(ctx, i0)
+}
+
+func (s implTypeTesterServerStub) YMultiArg(ctx ipc.ServerCall, i0 int32, i1 int32) (int32, int32, error) {
+	return s.impl.YMultiArg(ctx, i0, i1)
+}
+
+func (s implTypeTesterServerStub) YNoArgs(ctx ipc.ServerCall) error {
+	return s.impl.YNoArgs(ctx)
+}
+
+func (s implTypeTesterServerStub) ZStream(ctx *TypeTesterZStreamContextStub, i0 int32, i1 bool) error {
+	return s.impl.ZStream(ctx, i0, i1)
+}
+
+func (s implTypeTesterServerStub) Globber() *ipc.GlobState {
+	return s.gs
+}
+
+func (s implTypeTesterServerStub) Describe__() []ipc.InterfaceDesc {
+	return []ipc.InterfaceDesc{TypeTesterDesc}
+}
+
+// TypeTesterDesc describes the TypeTester interface.
+var TypeTesterDesc ipc.InterfaceDesc = descTypeTester
+
+// descTypeTester hides the desc to keep godoc clean.
+var descTypeTester = ipc.InterfaceDesc{
+	Name:    "TypeTester",
+	PkgPath: "v.io/x/ref/cmd/vrpc/test_base",
+	Doc:     "// TypeTester methods are listed in alphabetical order, to make it easier to\n// test Signature output, which sorts methods alphabetically.",
+	Methods: []ipc.MethodDesc{
+		{
+			Name: "EchoBool",
+			Doc:  "// Methods to test support for primitive types.",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // bool
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // bool
+			},
+		},
+		{
+			Name: "EchoFloat32",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // float32
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // float32
+			},
+		},
+		{
+			Name: "EchoFloat64",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // float64
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // float64
+			},
+		},
+		{
+			Name: "EchoInt32",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // int32
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // int32
+			},
+		},
+		{
+			Name: "EchoInt64",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // int64
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // int64
+			},
+		},
+		{
+			Name: "EchoString",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // string
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // string
+			},
+		},
+		{
+			Name: "EchoByte",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // byte
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // byte
+			},
+		},
+		{
+			Name: "EchoUint32",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // uint32
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // uint32
+			},
+		},
+		{
+			Name: "EchoUint64",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // uint64
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // uint64
+			},
+		},
+		{
+			Name: "XEchoArray",
+			Doc:  "// Methods to test support for composite types.",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // Array2Int
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // Array2Int
+			},
+		},
+		{
+			Name: "XEchoMap",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // map[int32]string
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // map[int32]string
+			},
+		},
+		{
+			Name: "XEchoSet",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // map[int32]struct{}
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // map[int32]struct{}
+			},
+		},
+		{
+			Name: "XEchoSlice",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // []int32
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // []int32
+			},
+		},
+		{
+			Name: "XEchoStruct",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // Struct
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // Struct
+			},
+		},
+		{
+			Name: "YMultiArg",
+			Doc:  "// Methods to test support for different number of arguments.",
+			InArgs: []ipc.ArgDesc{
+				{"I1", ``}, // int32
+				{"I2", ``}, // int32
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"O1", ``}, // int32
+				{"O2", ``}, // int32
+			},
+		},
+		{
+			Name: "YNoArgs",
+		},
+		{
+			Name: "ZStream",
+			Doc:  "// Methods to test support for streaming.",
+			InArgs: []ipc.ArgDesc{
+				{"NumStreamItems", ``}, // int32
+				{"StreamItem", ``},     // bool
+			},
+		},
+	},
+}
+
+// TypeTesterZStreamServerStream is the server stream for TypeTester.ZStream.
+type TypeTesterZStreamServerStream interface {
+	// SendStream returns the send side of the TypeTester.ZStream server stream.
+	SendStream() interface {
+		// Send places the item onto the output stream.  Returns errors encountered
+		// while sending.  Blocks if there is no buffer space; will unblock when
+		// buffer space is available.
+		Send(item bool) error
+	}
+}
+
+// TypeTesterZStreamContext represents the context passed to TypeTester.ZStream.
+type TypeTesterZStreamContext interface {
+	ipc.ServerCall
+	TypeTesterZStreamServerStream
+}
+
+// TypeTesterZStreamContextStub is a wrapper that converts ipc.StreamServerCall into
+// a typesafe stub that implements TypeTesterZStreamContext.
+type TypeTesterZStreamContextStub struct {
+	ipc.StreamServerCall
+}
+
+// Init initializes TypeTesterZStreamContextStub from ipc.StreamServerCall.
+func (s *TypeTesterZStreamContextStub) Init(call ipc.StreamServerCall) {
+	s.StreamServerCall = call
+}
+
+// SendStream returns the send side of the TypeTester.ZStream server stream.
+func (s *TypeTesterZStreamContextStub) SendStream() interface {
+	Send(item bool) error
+} {
+	return implTypeTesterZStreamContextSend{s}
+}
+
+type implTypeTesterZStreamContextSend struct {
+	s *TypeTesterZStreamContextStub
+}
+
+func (s implTypeTesterZStreamContextSend) Send(item bool) error {
+	return s.s.Send(item)
+}
diff --git a/cmd/vrpc/vrpc.go b/cmd/vrpc/vrpc.go
new file mode 100644
index 0000000..1241b0b
--- /dev/null
+++ b/cmd/vrpc/vrpc.go
@@ -0,0 +1,265 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+
+	"v.io/v23"
+	"v.io/v23/context"
+	"v.io/v23/ipc/reserved"
+	"v.io/v23/options"
+	"v.io/v23/vdl"
+	"v.io/v23/vdlroot/signature"
+	"v.io/x/lib/cmdline"
+	"v.io/x/ref/lib/vdl/build"
+	"v.io/x/ref/lib/vdl/codegen/vdlgen"
+	"v.io/x/ref/lib/vdl/compile"
+
+	_ "v.io/x/ref/profiles"
+)
+
+var gctx *context.T
+
+func main() {
+	var shutdown v23.Shutdown
+	gctx, shutdown = v23.Init()
+	exitCode := cmdVRPC.Main()
+	shutdown()
+	os.Exit(exitCode)
+}
+
+var cmdVRPC = &cmdline.Command{
+	Name:  "vrpc",
+	Short: "Vanadium Remote Procedure Call tool",
+	Long: `
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
+`,
+	// TODO(toddw): Add cmdServe, which will take an interface as input, and set
+	// up a server capable of handling the given methods.  When a request is
+	// received, it'll allow the user to respond via stdin.
+	Children: []*cmdline.Command{cmdSignature, cmdCall, cmdIdentify},
+}
+
+const serverDesc = `
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+`
+
+var cmdSignature = &cmdline.Command{
+	Run:   runSignature,
+	Name:  "signature",
+	Short: "Describe the interfaces of a Vanadium server",
+	Long: `
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
+`,
+	ArgsName: "<server> [method]",
+	ArgsLong: serverDesc + `
+[method] is the optional server method name.
+`,
+}
+
+var cmdCall = &cmdline.Command{
+	Run:   runCall,
+	Name:  "call",
+	Short: "Call a method of a Vanadium server",
+	Long: `
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
+`,
+	ArgsName: "<server> <method> [args...]",
+	ArgsLong: serverDesc + `
+<method> is the server method to call.
+
+[args...] are the positional input arguments, specified as VDL expressions.
+`,
+}
+
+var cmdIdentify = &cmdline.Command{
+	Run:   runIdentify,
+	Name:  "identify",
+	Short: "Reveal blessings presented by a Vanadium server",
+	Long: `
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+`,
+	ArgsName: "<server>",
+	ArgsLong: serverDesc,
+}
+
+func runSignature(cmd *cmdline.Command, args []string) error {
+	// Error-check args.
+	var server, method string
+	switch len(args) {
+	case 1:
+		server = args[0]
+	case 2:
+		server, method = args[0], args[1]
+	default:
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	// Get the interface or method signature, and pretty-print.  We print the
+	// named types after the signatures, to aid in readability.
+	ctx, cancel := context.WithTimeout(gctx, time.Minute)
+	defer cancel()
+	var types vdlgen.NamedTypes
+	if method != "" {
+		methodSig, err := reserved.MethodSignature(ctx, server, method, options.SkipResolveAuthorization{})
+		if err != nil {
+			return fmt.Errorf("MethodSignature failed: %v", err)
+		}
+		vdlgen.PrintMethod(cmd.Stdout(), methodSig, &types)
+		fmt.Fprintln(cmd.Stdout())
+		types.Print(cmd.Stdout())
+		return nil
+	}
+	ifacesSig, err := reserved.Signature(ctx, server, options.SkipResolveAuthorization{})
+	if err != nil {
+		return fmt.Errorf("Signature failed: %v", err)
+	}
+	for i, iface := range ifacesSig {
+		if i > 0 {
+			fmt.Fprintln(cmd.Stdout())
+		}
+		vdlgen.PrintInterface(cmd.Stdout(), iface, &types)
+		fmt.Fprintln(cmd.Stdout())
+	}
+	types.Print(cmd.Stdout())
+	return nil
+}
+
+func runCall(cmd *cmdline.Command, args []string) error {
+	// Error-check args, and set up argsdata with a comma-separated list of
+	// arguments, allowing each individual arg to already be comma-separated.
+	//
+	// TODO(toddw): Should we just space-separate the args instead?
+	if len(args) < 2 {
+		return cmd.UsageErrorf("must specify <server> and <method>")
+	}
+	server, method := args[0], args[1]
+	var argsdata string
+	for _, arg := range args[2:] {
+		arg := strings.TrimSpace(arg)
+		if argsdata == "" || strings.HasSuffix(argsdata, ",") || strings.HasPrefix(arg, ",") {
+			argsdata += arg
+		} else {
+			argsdata += "," + arg
+		}
+	}
+	// Get the method signature and parse args.
+	ctx, cancel := context.WithTimeout(gctx, time.Minute)
+	defer cancel()
+	methodSig, err := reserved.MethodSignature(ctx, server, method)
+	if err != nil {
+		return fmt.Errorf("MethodSignature failed: %v", err)
+	}
+	inargs, err := parseInArgs(argsdata, methodSig)
+	if err != nil {
+		// TODO: Print signature and example.
+		return err
+	}
+	// Start the method call.
+	call, err := v23.GetClient(ctx).StartCall(ctx, server, method, inargs)
+	if err != nil {
+		return fmt.Errorf("StartCall failed: %v", err)
+	}
+	// TODO(toddw): Fire off a goroutine to handle streaming inputs.
+	// Handle streaming results.
+StreamingResultsLoop:
+	for {
+		var item *vdl.Value
+		switch err := call.Recv(&item); {
+		case err == io.EOF:
+			break StreamingResultsLoop
+		case err != nil:
+			return fmt.Errorf("call.Recv failed: %v", err)
+		}
+		fmt.Fprintf(cmd.Stdout(), "<< %v\n", vdlgen.TypedConst(item, "", nil))
+	}
+	// Finish the method call.
+	outargs := make([]*vdl.Value, len(methodSig.OutArgs))
+	outptrs := make([]interface{}, len(outargs))
+	for i := range outargs {
+		outptrs[i] = &outargs[i]
+	}
+	if err := call.Finish(outptrs...); err != nil {
+		return fmt.Errorf("call.Finish failed: %v", err)
+	}
+	// Pretty-print results.
+	for i, arg := range outargs {
+		if i > 0 {
+			fmt.Fprint(cmd.Stdout(), " ")
+		}
+		fmt.Fprint(cmd.Stdout(), vdlgen.TypedConst(arg, "", nil))
+	}
+	fmt.Fprintln(cmd.Stdout())
+	return nil
+}
+
+func parseInArgs(argsdata string, methodSig signature.Method) ([]interface{}, error) {
+	if len(methodSig.InArgs) == 0 {
+		return nil, nil
+	}
+	var intypes []*vdl.Type
+	for _, inarg := range methodSig.InArgs {
+		intypes = append(intypes, inarg.Type)
+	}
+	env := compile.NewEnv(-1)
+	inargs := build.BuildExprs(argsdata, intypes, env)
+	if err := env.Errors.ToError(); err != nil {
+		return nil, fmt.Errorf("can't parse in-args:\n%v", err)
+	}
+	if got, want := len(inargs), len(methodSig.InArgs); got != want {
+		return nil, fmt.Errorf("got %d args, want %d", got, want)
+	}
+	// Translate []*vdl.Value to []interface, with each item still *vdl.Value.
+	var ret []interface{}
+	for _, arg := range inargs {
+		ret = append(ret, arg)
+	}
+	return ret, nil
+}
+
+func runIdentify(cmd *cmdline.Command, args []string) error {
+	if len(args) != 1 {
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	server := args[0]
+	ctx, cancel := context.WithTimeout(gctx, time.Minute)
+	defer cancel()
+	// The method name does not matter - only interested in authentication,
+	// not in actually making an RPC.
+	call, err := v23.GetClient(ctx).StartCall(ctx, server, "", nil)
+	if err != nil {
+		return fmt.Errorf(`client.StartCall(%q, "", nil) failed with %v`, server, err)
+	}
+	valid, presented := call.RemoteBlessings()
+	fmt.Fprintf(cmd.Stdout(), "PRESENTED:  %v\nVALID:      %v\n", presented, valid)
+	return nil
+}
diff --git a/cmd/vrpc/vrpc_test.go b/cmd/vrpc/vrpc_test.go
new file mode 100644
index 0000000..2b442ae
--- /dev/null
+++ b/cmd/vrpc/vrpc_test.go
@@ -0,0 +1,300 @@
+package main
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+
+	"v.io/v23"
+	"v.io/v23/ipc"
+	"v.io/x/lib/vlog"
+
+	"v.io/x/ref/cmd/vrpc/test_base"
+	"v.io/x/ref/lib/testutil"
+	_ "v.io/x/ref/profiles"
+)
+
+type server struct{}
+
+// TypeTester interface implementation
+
+func (*server) EchoBool(call ipc.ServerCall, i1 bool) (bool, error) {
+	vlog.VI(2).Info("EchoBool(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat32(call ipc.ServerCall, i1 float32) (float32, error) {
+	vlog.VI(2).Info("EchoFloat32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat64(call ipc.ServerCall, i1 float64) (float64, error) {
+	vlog.VI(2).Info("EchoFloat64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt32(call ipc.ServerCall, i1 int32) (int32, error) {
+	vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt64(call ipc.ServerCall, i1 int64) (int64, error) {
+	vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoString(call ipc.ServerCall, i1 string) (string, error) {
+	vlog.VI(2).Info("EchoString(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoByte(call ipc.ServerCall, i1 byte) (byte, error) {
+	vlog.VI(2).Info("EchoByte(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint32(call ipc.ServerCall, i1 uint32) (uint32, error) {
+	vlog.VI(2).Info("EchoUint32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint64(call ipc.ServerCall, i1 uint64) (uint64, error) {
+	vlog.VI(2).Info("EchoUint64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoArray(call ipc.ServerCall, i1 test_base.Array2Int) (test_base.Array2Int, error) {
+	vlog.VI(2).Info("XEchoArray(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoMap(call ipc.ServerCall, i1 map[int32]string) (map[int32]string, error) {
+	vlog.VI(2).Info("XEchoMap(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSet(call ipc.ServerCall, i1 map[int32]struct{}) (map[int32]struct{}, error) {
+	vlog.VI(2).Info("XEchoSet(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSlice(call ipc.ServerCall, i1 []int32) ([]int32, error) {
+	vlog.VI(2).Info("XEchoSlice(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoStruct(call ipc.ServerCall, i1 test_base.Struct) (test_base.Struct, error) {
+	vlog.VI(2).Info("XEchoStruct(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) YMultiArg(call ipc.ServerCall, i1, i2 int32) (int32, int32, error) {
+	vlog.VI(2).Info("YMultiArg(%v,%v) was called.", i1, i2)
+	return i1, i2, nil
+}
+
+func (*server) YNoArgs(call ipc.ServerCall) error {
+	vlog.VI(2).Info("YNoArgs() was called.")
+	return nil
+}
+
+func (*server) ZStream(ctx test_base.TypeTesterZStreamContext, nStream int32, item bool) error {
+	vlog.VI(2).Info("ZStream(%v,%v) was called.", nStream, item)
+	sender := ctx.SendStream()
+	for i := int32(0); i < nStream; i++ {
+		sender.Send(item)
+	}
+	return nil
+}
+
+func initTest(t *testing.T) (name string, shutdown v23.Shutdown) {
+	// The gctx initialized here is the global context defined in vrpc.go.
+	gctx, shutdown = testutil.InitForTest()
+
+	ipcServer, err := v23.NewServer(gctx)
+	if err != nil {
+		t.Fatalf("NewServer failed: %v", err)
+		return
+	}
+	endpoints, err := ipcServer.Listen(v23.GetListenSpec(gctx))
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+		return
+	}
+	name = endpoints[0].Name()
+	obj := test_base.TypeTesterServer(&server{})
+	if err := ipcServer.Serve("", obj, nil); err != nil {
+		t.Fatalf("Serve failed: %v", err)
+		return name, shutdown
+	}
+	return name, shutdown
+}
+
+func TestSignature(t *testing.T) {
+	name, shutdown := initTest(t)
+	defer shutdown()
+	var stdout, stderr bytes.Buffer
+	cmdVRPC.Init(nil, &stdout, &stderr)
+
+	if err := cmdVRPC.Execute([]string{"signature", name}); err != nil {
+		t.Errorf("%v", err)
+		return
+	}
+	wantSig := `// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type "v.io/x/ref/cmd/vrpc/test_base".TypeTester interface {
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
+	// Methods to test support for composite types.
+	XEchoArray(I1 "v.io/x/ref/cmd/vrpc/test_base".Array2Int) (O1 "v.io/x/ref/cmd/vrpc/test_base".Array2Int | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 "v.io/x/ref/cmd/vrpc/test_base".Struct) (O1 "v.io/x/ref/cmd/vrpc/test_base".Struct | error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1 int32, I2 int32) (O1 int32, O2 int32 | error)
+	YNoArgs() error
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+}
+
+// Reserved methods implemented by the IPC framework.  Each method name is prefixed with a double underscore "__".
+type __Reserved interface {
+	// Glob returns all entries matching the pattern.
+	__Glob(pattern string) stream<any, any> error
+	// MethodSignature returns the signature for the given method.
+	__MethodSignature(method string) ("signature".Method | error)
+	// Signature returns all interface signatures implemented by the object.
+	__Signature() ([]"signature".Interface | error)
+}
+
+type "signature".Arg struct {
+	Name string
+	Doc string
+	Type typeobject
+}
+
+type "signature".Embed struct {
+	Name string
+	PkgPath string
+	Doc string
+}
+
+type "signature".Interface struct {
+	Name string
+	PkgPath string
+	Doc string
+	Embeds []"signature".Embed
+	Methods []"signature".Method
+}
+
+type "signature".Method struct {
+	Name string
+	Doc string
+	InArgs []"signature".Arg
+	OutArgs []"signature".Arg
+	InStream ?"signature".Arg
+	OutStream ?"signature".Arg
+	Tags []any
+}
+
+type "v.io/x/ref/cmd/vrpc/test_base".Array2Int [2]int32
+
+type "v.io/x/ref/cmd/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+`
+	if got, want := stdout.String(), wantSig; got != want {
+		t.Errorf("got stdout %q, want %q", got, want)
+	}
+	if got, want := stderr.String(), ""; got != want {
+		t.Errorf("got stderr %q, want %q", got, want)
+	}
+}
+
+func TestMethodSignature(t *testing.T) {
+	name, shutdown := initTest(t)
+	defer shutdown()
+
+	tests := []struct {
+		Method, Want string
+	}{
+		// Spot-check some individual methods.
+		{"EchoByte", `EchoByte(I1 byte) (O1 byte | error)`},
+		{"EchoFloat32", `EchoFloat32(I1 float32) (O1 float32 | error)`},
+		{"XEchoStruct", `
+XEchoStruct(I1 "v.io/x/ref/cmd/vrpc/test_base".Struct) (O1 "v.io/x/ref/cmd/vrpc/test_base".Struct | error)
+
+type "v.io/x/ref/cmd/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"signature", name, test.Method}); err != nil {
+			t.Errorf("%q failed: %v", test.Method, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}
+
+func TestCall(t *testing.T) {
+	name, shutdown := initTest(t)
+	defer shutdown()
+
+	tests := []struct {
+		Method, InArgs, Want string
+	}{
+		{"EchoBool", `true`, `true`},
+		{"EchoBool", `false`, `false`},
+		{"EchoFloat32", `1.2`, `float32(1.2)`},
+		{"EchoFloat64", `-3.4`, `float64(-3.4)`},
+		{"EchoInt32", `11`, `int32(11)`},
+		{"EchoInt64", `-22`, `int64(-22)`},
+		{"EchoString", `"abc"`, `"abc"`},
+		{"EchoByte", `33`, `byte(33)`},
+		{"EchoUint32", `44`, `uint32(44)`},
+		{"EchoUint64", `55`, `uint64(55)`},
+		{"XEchoArray", `{1,2}`, `"v.io/x/ref/cmd/vrpc/test_base".Array2Int{1, 2}`},
+		{"XEchoMap", `{1:"a"}`, `map[int32]string{1: "a"}`},
+		{"XEchoSet", `{1}`, `set[int32]{1}`},
+		{"XEchoSlice", `{1,2}`, `[]int32{1, 2}`},
+		{"XEchoStruct", `{1,2}`, `"v.io/x/ref/cmd/vrpc/test_base".Struct{X: 1, Y: 2}`},
+		{"YMultiArg", `1,2`, `int32(1) int32(2)`},
+		{"YNoArgs", ``, ``},
+		{"ZStream", `2,true`, `<< true
+<< true`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"call", name, test.Method, test.InArgs}); err != nil {
+			t.Errorf("%q(%s) failed: %v", test.Method, test.InArgs, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}
diff --git a/tools/vrun/doc.go b/cmd/vrun/doc.go
similarity index 100%
rename from tools/vrun/doc.go
rename to cmd/vrun/doc.go
diff --git a/tools/vrun/internal/v23_test.go b/cmd/vrun/internal/v23_test.go
similarity index 100%
rename from tools/vrun/internal/v23_test.go
rename to cmd/vrun/internal/v23_test.go
diff --git a/tools/vrun/internal/vrun_test_helper.go b/cmd/vrun/internal/vrun_test_helper.go
similarity index 100%
rename from tools/vrun/internal/vrun_test_helper.go
rename to cmd/vrun/internal/vrun_test_helper.go
diff --git a/tools/vrun/internal/vrun_v23_test.go b/cmd/vrun/internal/vrun_v23_test.go
similarity index 78%
rename from tools/vrun/internal/vrun_v23_test.go
rename to cmd/vrun/internal/vrun_v23_test.go
index 9e789ce..30efa19 100644
--- a/tools/vrun/internal/vrun_v23_test.go
+++ b/cmd/vrun/internal/vrun_v23_test.go
@@ -10,11 +10,11 @@
 )
 
 func V23TestAgentd(t *v23tests.T) {
-	vrunBin := t.BuildGoPkg("v.io/x/ref/tools/vrun")
+	vrunBin := t.BuildGoPkg("v.io/x/ref/cmd/vrun")
 	pingpongBin := t.BuildGoPkg("v.io/x/ref/security/agent/pingpong")
 	agentdBin := t.BuildGoPkg("v.io/x/ref/security/agent/agentd")
-	helperBin := t.BuildGoPkg("v.io/x/ref/tools/vrun/internal")
-	principalBin := t.BuildGoPkg("v.io/x/ref/tools/principal")
+	helperBin := t.BuildGoPkg("v.io/x/ref/cmd/vrun/internal")
+	principalBin := t.BuildGoPkg("v.io/x/ref/cmd/principal")
 
 	v23tests.RunRootMT(t, "--veyron.tcp.address=127.0.0.1:0")
 
diff --git a/tools/vrun/vrun.go b/cmd/vrun/vrun.go
similarity index 100%
rename from tools/vrun/vrun.go
rename to cmd/vrun/vrun.go
diff --git a/examples/tunnel/tunneld/tunneld_v23_test.go b/examples/tunnel/tunneld/tunneld_v23_test.go
index 8851005..0086af4 100644
--- a/examples/tunnel/tunneld/tunneld_v23_test.go
+++ b/examples/tunnel/tunneld/tunneld_v23_test.go
@@ -20,7 +20,7 @@
 
 	tunneldBin := t.BuildGoPkg("v.io/x/ref/examples/tunnel/tunneld")
 	vsh := t.BuildGoPkg("v.io/x/ref/examples/tunnel/vsh")
-	mounttableBin := t.BuildGoPkg("v.io/x/ref/tools/mounttable")
+	mounttableBin := t.BuildGoPkg("v.io/x/ref/cmd/mounttable")
 
 	port, err := testutil.FindUnusedPort()
 	if err != nil {
diff --git a/lib/testutil/v23tests/internal/cached_test.go b/lib/testutil/v23tests/internal/cached_test.go
index 651e7f6..6a8127d 100644
--- a/lib/testutil/v23tests/internal/cached_test.go
+++ b/lib/testutil/v23tests/internal/cached_test.go
@@ -31,7 +31,7 @@
 // build build's a binary and appends it's modtime to the
 // global slice modTimes
 func build(i *v23tests.T) {
-	nsBin := i.BuildGoPkg("v.io/x/ref/tools/namespace")
+	nsBin := i.BuildGoPkg("v.io/x/ref/cmd/namespace")
 	fi, err := os.Stat(nsBin.Path())
 	if err != nil {
 		i.Fatal()
diff --git a/lib/testutil/v23tests/v23tests_test.go b/lib/testutil/v23tests/v23tests_test.go
index 480ad07..64ceb99 100644
--- a/lib/testutil/v23tests/v23tests_test.go
+++ b/lib/testutil/v23tests/v23tests_test.go
@@ -48,7 +48,7 @@
 
 	v23tests.RunRootMT(env, "--veyron.tcp.address=127.0.0.1:0")
 	proxyBin := env.BuildGoPkg("v.io/x/ref/services/proxy/proxyd")
-	nsBin := env.BuildGoPkg("v.io/x/ref/tools/namespace")
+	nsBin := env.BuildGoPkg("v.io/x/ref/cmd/namespace")
 
 	mt, ok := env.GetVar("NAMESPACE_ROOT")
 	if !ok || len(mt) == 0 {
diff --git a/security/agent/agent_v23_test.go b/security/agent/agent_v23_test.go
index 03100ce..73a6ef0 100644
--- a/security/agent/agent_v23_test.go
+++ b/security/agent/agent_v23_test.go
@@ -127,7 +127,7 @@
 	rootMTArg := "--veyron.namespace.root=" + ns
 
 	agentBin := i.BuildGoPkg("v.io/x/ref/security/agent/agentd")
-	vrun := i.BuildGoPkg("v.io/x/ref/tools/vrun")
+	vrun := i.BuildGoPkg("v.io/x/ref/cmd/vrun")
 
 	pingpongBin := buildAndRunPingpongServer(i, rootMTArg)
 	credentials := "VEYRON_CREDENTIALS=" + i.NewTempDir()
diff --git a/services/GO.PACKAGE b/services/GO.PACKAGE
index b6de7af..072df54 100644
--- a/services/GO.PACKAGE
+++ b/services/GO.PACKAGE
@@ -4,7 +4,7 @@
 			{"allow": "v.io/x/ref/services/..."},
 			{"allow": "v.io/x/ref/lib/...", "comment":"temporarily allowing dependency from lib"},
 			{"allow": "v.io/x/ref/profiles/...", "comment":"temporarily allowing dependency from profiles"},
-			{"allow": "v.io/x/ref/tools/...", "comment":"temporarily allowing dependency from veyron/tools"},
+			{"allow": "v.io/x/ref/cmd/...", "comment":"temporarily allowing dependency from veyron/tools"},
 			{"deny": "..."}
 		]
 	}
diff --git a/services/identity/identityd/identityd_v23_test.go b/services/identity/identityd/identityd_v23_test.go
index a47d460..07c6aac 100644
--- a/services/identity/identityd/identityd_v23_test.go
+++ b/services/identity/identityd/identityd_v23_test.go
@@ -79,7 +79,7 @@
 	i.BuildGoPkg("v.io/x/ref/services/identity/identityd_test").Start(args...)
 
 	// Use the principal tool to seekblessings.
-	principal := i.BuildGoPkg("v.io/x/ref/tools/principal")
+	principal := i.BuildGoPkg("v.io/x/ref/cmd/principal")
 	// Test an initial seekblessings call.
 	seekBlessings(i, principal, httpaddr)
 	// Test that a subsequent call succeeds with the same
diff --git a/services/mgmt/application/applicationd/applicationd_v23_test.go b/services/mgmt/application/applicationd/applicationd_v23_test.go
index 4649be3..a83f38f 100644
--- a/services/mgmt/application/applicationd/applicationd_v23_test.go
+++ b/services/mgmt/application/applicationd/applicationd_v23_test.go
@@ -64,7 +64,7 @@
 	i.BuildGoPkg("v.io/x/ref/services/mgmt/application/applicationd").Start(args...)
 
 	// Build the client binary.
-	clientBin := i.BuildGoPkg("v.io/x/ref/tools/application")
+	clientBin := i.BuildGoPkg("v.io/x/ref/cmd/application")
 
 	// Generate publisher blessings
 	principal, err := vsecurity.NewPrincipal()
diff --git a/services/mgmt/binary/binaryd/binaryd_v23_test.go b/services/mgmt/binary/binaryd/binaryd_v23_test.go
index 034cfa4..ca3a04f 100644
--- a/services/mgmt/binary/binaryd/binaryd_v23_test.go
+++ b/services/mgmt/binary/binaryd/binaryd_v23_test.go
@@ -103,7 +103,7 @@
 
 	// Build the required binaries.
 	binaryRepoBin := i.BuildGoPkg("v.io/x/ref/services/mgmt/binary/binaryd")
-	clientBin := i.BuildGoPkg("v.io/x/ref/tools/binary")
+	clientBin := i.BuildGoPkg("v.io/x/ref/cmd/binary")
 
 	// Generate credentials.
 	serverCred, serverPrin := security.NewCredentials("server")
diff --git a/services/mgmt/build/buildd/buildd_v23_test.go b/services/mgmt/build/buildd/buildd_v23_test.go
index 9f6e3ec..3fafbe7 100644
--- a/services/mgmt/build/buildd/buildd_v23_test.go
+++ b/services/mgmt/build/buildd/buildd_v23_test.go
@@ -66,7 +66,7 @@
 		"build", buildServerName, "test",
 	}
 	buildEnv := []string{"GOPATH=" + testGoPath, "GOROOT=" + goRoot, "TMPDIR=" + testBinDir}
-	buildBin := i.BuildGoPkg("v.io/x/ref/tools/build")
+	buildBin := i.BuildGoPkg("v.io/x/ref/cmd/build")
 	buildBin.WithEnv(buildEnv...).Start(buildArgs...).WaitOrDie(os.Stdout, os.Stderr)
 	var testOut bytes.Buffer
 	testCmd := exec.Command(testBinFile)
diff --git a/services/mgmt/profile/profiled/profiled_v23_test.go b/services/mgmt/profile/profiled/profiled_v23_test.go
index e3c8e18..5ef410e 100644
--- a/services/mgmt/profile/profiled/profiled_v23_test.go
+++ b/services/mgmt/profile/profiled/profiled_v23_test.go
@@ -52,7 +52,7 @@
 	}
 	i.BuildGoPkg("v.io/x/ref/services/mgmt/profile/profiled").Start(args...)
 
-	clientBin := i.BuildGoPkg("v.io/x/ref/tools/profile")
+	clientBin := i.BuildGoPkg("v.io/x/ref/cmd/profile")
 
 	// Create a profile.
 	const profile = "test-profile"
diff --git a/services/mounttable/mounttabled/mounttabled_v23_test.go b/services/mounttable/mounttabled/mounttabled_v23_test.go
index 7123942..115976a 100644
--- a/services/mounttable/mounttabled/mounttabled_v23_test.go
+++ b/services/mounttable/mounttabled/mounttabled_v23_test.go
@@ -25,7 +25,7 @@
 
 	name, _ := i.GetVar("NAMESPACE_ROOT")
 
-	clientBin := i.BuildGoPkg("v.io/x/ref/tools/mounttable")
+	clientBin := i.BuildGoPkg("v.io/x/ref/cmd/mounttable")
 
 	// Get the neighborhood endpoint from the mounttable.
 	neighborhoodEndpoint := clientBin.Start("glob", name, "nh").ExpectSetEventuallyRE(`^nh (.*) \(TTL .*\)$`)[0][1]