diff --git a/cmd/apps_test.go b/cmd/apps_test.go
index afc8d522b..ed9137c49 100644
--- a/cmd/apps_test.go
+++ b/cmd/apps_test.go
@@ -141,7 +141,8 @@ func TestAppsInfo(t *testing.T) {
         "started": "2016-08-22T17:42:16Z",
         "name": "lorem-ipsum-cmd-1911796442-48b58",
         "release": "v2",
-        "type": "cmd"
+        "type": "cmd",
+        "replicas": 1
       }
     ]
 }`)
@@ -204,7 +205,7 @@ owner:    dolar-sit-amet
 id:       lorem-ipsum
 
 === lorem-ipsum Processes
---- cmd:
+--- cmd (started): 1
 lorem-ipsum-cmd-1911796442-48b58 up (v2)
 
 === lorem-ipsum Domains
diff --git a/cmd/cmd.go b/cmd/cmd.go
index ae9f199c2..6485f59da 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -70,6 +70,8 @@ type Commander interface {
 	PsList(string, int) error
 	PsScale(string, []string) error
 	PsRestart(string, string) error
+	PsStop(string, []string) error
+	PsStart(string, []string) error
 	RegistryList(string) error
 	RegistrySet(string, []string) error
 	RegistryUnset(string, []string) error
diff --git a/cmd/ps.go b/cmd/ps.go
index 4d4096964..c5b8857a9 100644
--- a/cmd/ps.go
+++ b/cmd/ps.go
@@ -68,6 +68,65 @@ func (d *DryccCmd) PsScale(appID string, targets []string) error {
 	return nil
 }
 
+// PsStop stop an app's processes.
+func (d *DryccCmd) PsStop(appID string, targets []string) error {
+	s, appID, err := load(d.ConfigFile, appID)
+	if err != nil {
+		return err
+	}
+
+	d.Printf("Stopping processes... but first, %s!\n", drinkOfChoice())
+	startTime := time.Now()
+	quit := progress(d.WOut)
+	tps := map[string][]string{"types": targets}
+	err = ps.Stop(s.Client, appID, tps)
+	quit <- true
+	<-quit
+	if d.checkAPICompatibility(s.Client, err) != nil {
+		return err
+	}
+
+	d.Printf("done in %ds\n", int(time.Since(startTime).Seconds()))
+
+	processes, _, err := ps.List(s.Client, appID, s.Limit)
+	if err != nil {
+		return err
+	}
+
+	printProcesses(appID, processes, d.WOut)
+	return nil
+}
+
+// PsStart start an app's processes.
+func (d *DryccCmd) PsStart(appID string, targets []string) error {
+	s, appID, err := load(d.ConfigFile, appID)
+	if err != nil {
+		return err
+	}
+
+	d.Printf("Starting processes... but first, %s!\n", drinkOfChoice())
+	startTime := time.Now()
+	quit := progress(d.WOut)
+
+	tps := map[string][]string{"types": targets}
+	err = ps.Start(s.Client, appID, tps)
+	quit <- true
+	<-quit
+	if d.checkAPICompatibility(s.Client, err) != nil {
+		return err
+	}
+
+	d.Printf("done in %ds\n", int(time.Since(startTime).Seconds()))
+
+	processes, _, err := ps.List(s.Client, appID, s.Limit)
+	if err != nil {
+		return err
+	}
+
+	printProcesses(appID, processes, d.WOut)
+	return nil
+}
+
 // PsRestart restarts an app's processes.
 func (d *DryccCmd) PsRestart(appID, target string) error {
 	s, appID, err := load(d.ConfigFile, appID)
@@ -109,7 +168,7 @@ func printProcesses(appID string, input []api.Pods, wOut io.Writer) {
 	fmt.Fprintf(wOut, "=== %s Processes\n", appID)
 
 	for _, process := range processes {
-		fmt.Fprintf(wOut, "--- %s:\n", process.Type)
+		fmt.Fprintf(wOut, "--- %s (%s): %d\n", process.Type, process.Status, process.Replicas)
 
 		for _, pod := range process.PodsList {
 			fmt.Fprintf(wOut, "%s %s (%s)\n", pod.Name, pod.State, pod.Release)
diff --git a/cmd/ps_test.go b/cmd/ps_test.go
index 2d490ed43..a5c2519ff 100644
--- a/cmd/ps_test.go
+++ b/cmd/ps_test.go
@@ -54,27 +54,29 @@ func TestPrintProcesses(t *testing.T) {
 
 	pods := []api.Pods{
 		{
-			Release: "v3",
-			Name:    "benign-quilting-web-4084101150-c871y",
-			Type:    "web",
-			State:   "up",
-			Started: time.Time{},
+			Release:  "v3",
+			Name:     "benign-quilting-web-4084101150-c871y",
+			Type:     "web",
+			State:    "up",
+			Started:  time.Time{},
+			Replicas: 1,
 		},
 		{
-			Release: "v3",
-			Name:    "benign-quilting-worker-4084101150-c871y",
-			Type:    "worker",
-			State:   "up",
-			Started: time.Time{},
+			Release:  "v3",
+			Name:     "benign-quilting-worker-4084101150-c871y",
+			Type:     "worker",
+			State:    "up",
+			Started:  time.Time{},
+			Replicas: 1,
 		},
 	}
 
 	printProcesses("appname", pods, &b)
 
 	assert.Equal(t, b.String(), `=== appname Processes
---- web:
+--- web (started): 1
 benign-quilting-web-4084101150-c871y up (v3)
---- worker:
+--- worker (started): 1
 benign-quilting-worker-4084101150-c871y up (v3)
 `, "output")
 }
@@ -101,7 +103,8 @@ func TestPsList(t *testing.T) {
 					"type": "web",
 					"name": "foo-web-4084101150-c871y",
 					"state": "up",
-					"started": "2016-02-13T00:47:52"
+					"started": "2016-02-13T00:47:52",
+					"replicas": 1
 				}
 			]
 		}`)
@@ -111,7 +114,7 @@ func TestPsList(t *testing.T) {
 	assert.NoErr(t, err)
 
 	assert.Equal(t, b.String(), `=== foo Processes
---- web:
+--- web (started): 1
 foo-web-4084101150-c871y up (v2)
 `, "output")
 }
@@ -171,7 +174,8 @@ func TestPsScale(t *testing.T) {
 					"type": "web",
 					"name": "foo-web-4084101150-c871y",
 					"state": "up",
-					"started": "2016-02-13T00:47:52"
+					"started": "2016-02-13T00:47:52",
+					"replicas": 1
 				}
 			]
 		}`)
@@ -189,7 +193,7 @@ func TestPsScale(t *testing.T) {
 	assert.Equal(t, testutil.StripProgress(b.String()), `Scaling processes... but first, coffee!
 done in 0s
 === foo Processes
---- web:
+--- web (started): 1
 foo-web-4084101150-c871y up (v2)
 `, "output")
 }
@@ -212,7 +216,8 @@ func TestPsRestart(t *testing.T) {
 				"type": "web",
 				"name": "foo-web-4084101150-c871y",
 				"state": "up",
-				"started": "2016-02-13T00:47:52"
+				"started": "2016-02-13T00:47:52",
+				"replicas": 1
 		}
 ]`)
 	})
@@ -223,7 +228,7 @@ func TestPsRestart(t *testing.T) {
 	assert.Equal(t, testutil.StripProgress(b.String()), `Restarting processes... but first, coffee!
 done in 0s
 === foo Processes
---- web:
+--- web (started): 1
 foo-web-4084101150-c871y up (v2)
 `, "output")
 
@@ -248,7 +253,8 @@ Could not find any processes to restart
 				"type": "web",
 				"name": "testapp-web-4084101150-c871y",
 				"state": "up",
-				"started": "2016-02-13T00:47:52"
+				"started": "2016-02-13T00:47:52",
+				"replicas": 1
 			}
 		]`)
 	})
@@ -260,7 +266,7 @@ Could not find any processes to restart
 	assert.Equal(t, testutil.StripProgress(b.String()), `Restarting processes... but first, coffee!
 done in 0s
 === testapp Processes
---- web:
+--- web (started): 1
 testapp-web-4084101150-c871y up (v2)
 `, "output")
 
@@ -272,7 +278,8 @@ testapp-web-4084101150-c871y up (v2)
 				"type": "web",
 				"name": "newapp-web-4084101150-c871y",
 				"state": "up",
-				"started": "2016-02-13T00:47:52"
+				"started": "2016-02-13T00:47:52",
+				"replicas": 1
 			}
 		]`)
 	})
@@ -284,7 +291,7 @@ testapp-web-4084101150-c871y up (v2)
 	assert.Equal(t, testutil.StripProgress(b.String()), `Restarting processes... but first, coffee!
 done in 0s
 === newapp Processes
---- web:
+--- web (started): 1
 newapp-web-4084101150-c871y up (v2)
 `, "output")
 
diff --git a/cmd/resources.go b/cmd/resources.go
index 26e4db329..315e10247 100644
--- a/cmd/resources.go
+++ b/cmd/resources.go
@@ -269,8 +269,7 @@ func maxNum(tempArray ...int) int {
 // parseParams transfer params to map
 func parseParams(params []string) (map[string]interface{}, error) {
 	paramsMap := make(map[string]interface{})
-
-	regex := regexp.MustCompile(`^([A-z_]+[A-z0-9_]*)=([\s\S]*)$`)
+	regex := regexp.MustCompile(`^([A-z_]+[A-z0-9_]*)((\.){1}([A-z0-9_]+))*=([\s\S]*)$`)
 	for _, param := range params {
 		if regex.MatchString(param) {
 			captures := regex.FindStringSubmatch(param)
diff --git a/go.mod b/go.mod
index 6c4184236..13110bedd 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.13
 require (
 	github.com/arschles/assert v1.0.1-0.20191213221312-71f210f9375a
 	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
-	github.com/drycc/controller-sdk-go v0.0.0-20201013084049-82230b1dc54f
+	github.com/drycc/controller-sdk-go v0.0.0-20201015015256-370f01036885
 	github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852
 	github.com/olekukonko/tablewriter v0.0.4
 	golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
diff --git a/go.sum b/go.sum
index b5c885dab..07064b860 100644
--- a/go.sum
+++ b/go.sum
@@ -42,6 +42,8 @@ github.com/drycc/controller-sdk-go v0.0.0-20200914062048-dcf027e6dd1a h1:sQEQ8KU
 github.com/drycc/controller-sdk-go v0.0.0-20200914062048-dcf027e6dd1a/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
 github.com/drycc/controller-sdk-go v0.0.0-20201013084049-82230b1dc54f h1:Lwm3ijm8W+STLHOOmumLSQRvCkUTuya+XkGM+VNFfGA=
 github.com/drycc/controller-sdk-go v0.0.0-20201013084049-82230b1dc54f/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
+github.com/drycc/controller-sdk-go v0.0.0-20201015015256-370f01036885 h1:lA6ERNPzsqPeEcoPX5s/G7eMu7NH6cJh8ZyOtXAcVxM=
+github.com/drycc/controller-sdk-go v0.0.0-20201015015256-370f01036885/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
 github.com/drycc/pkg v0.0.0-20190129033019-bcdffff0fcb3 h1:QRAbL97/hJecXQzaSONMCiwt1JjBKAAMKK0qJW5sgIM=
 github.com/drycc/pkg v0.0.0-20190129033019-bcdffff0fcb3/go.mod h1:zNgTT6kuGZOKMIdSrjskIw5fctdbbszqiTPEt3ffxHw=
 github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852 h1:OsWH7jrv2i32rkvHFuj3yVpGMR+A6heRge9tm01XR/U=
diff --git a/parser/ps.go b/parser/ps.go
index 9c20f5081..c91dffe0c 100644
--- a/parser/ps.go
+++ b/parser/ps.go
@@ -13,6 +13,8 @@ Valid commands for processes:
 ps:list        list application processes
 ps:restart     restart an application or its process types
 ps:scale       scale processes (e.g. web=4 worker=2)
+ps:stop        stop processes (e.g. web worker)
+ps:start       start processes (e.g. web worker)
 
 Use 'drycc help [command]' to learn more.
 `
@@ -24,6 +26,10 @@ Use 'drycc help [command]' to learn more.
 		return psRestart(argv, cmdr)
 	case "ps:scale":
 		return psScale(argv, cmdr)
+	case "ps:stop":
+		return psStop(argv, cmdr)
+	case "ps:start":
+		return psStart(argv, cmdr)
 	default:
 		if printHelp(argv, usage) {
 			return nil
@@ -113,3 +119,55 @@ Options:
 	apps := safeGetValue(args, "--app")
 	return cmdr.PsScale(apps, args["<type>=<num>"].([]string))
 }
+
+func psStop(argv []string, cmdr cmd.Commander) error {
+	usage := `
+Stop an application's processes by type.
+
+Usage: drycc ps:stop <type>... [options]
+
+Arguments:
+  <type>
+    the process name as defined in your Procfile, such as 'web' or 'worker'.
+    Note that Dockerfile apps have a default 'cmd' process type.
+
+Options:
+  -a --app=<app>
+    the uniquely identifiable name for the application.
+`
+
+	args, err := docopt.Parse(usage, argv, true, "", false, true)
+
+	if err != nil {
+		return err
+	}
+
+	apps := safeGetValue(args, "--app")
+	return cmdr.PsStop(apps, args["<type>"].([]string))
+}
+
+func psStart(argv []string, cmdr cmd.Commander) error {
+	usage := `
+Start an application's processes by type.
+
+Usage: drycc ps:start <type>... [options]
+
+Arguments:
+  <type>
+    the process name as defined in your Procfile, such as 'web' or 'worker'.
+    Note that Dockerfile apps have a default 'cmd' process type.
+
+Options:
+  -a --app=<app>
+    the uniquely identifiable name for the application.
+`
+
+	args, err := docopt.Parse(usage, argv, true, "", false, true)
+
+	if err != nil {
+		return err
+	}
+
+	apps := safeGetValue(args, "--app")
+	return cmdr.PsStart(apps, args["<type>"].([]string))
+}
diff --git a/parser/ps_test.go b/parser/ps_test.go
index ae02a010b..787643110 100644
--- a/parser/ps_test.go
+++ b/parser/ps_test.go
@@ -24,6 +24,14 @@ func (d FakeDryccCmd) PsRestart(string, string) error {
 	return errors.New("ps:restart")
 }
 
+func (d FakeDryccCmd) PsStop(string, []string) error {
+	return errors.New("ps:stop")
+}
+
+func (d FakeDryccCmd) PsStart(string, []string) error {
+	return errors.New("ps:start")
+}
+
 func TestPs(t *testing.T) {
 	t.Parallel()
 
@@ -61,6 +69,14 @@ func TestPs(t *testing.T) {
 			args:     []string{"ps"},
 			expected: "ps:list",
 		},
+		{
+			args:     []string{"ps:stop", "web"},
+			expected: "",
+		},
+		{
+			args:     []string{"ps:start", "web"},
+			expected: "",
+		},
 	}
 
 	// For each case, check that calling the route with the arguments
