diff --git a/cmd/alp/cmd/common_test.go b/cmd/alp/cmd/common_test.go
index 275aae5..f87a116 100644
--- a/cmd/alp/cmd/common_test.go
+++ b/cmd/alp/cmd/common_test.go
@@ -10,22 +10,22 @@ import (
 func TestCommonFlags(t *testing.T) {
 	tempDir := t.TempDir()
 
-	tempLog, err := testutil.CreateTempDirAndFile(tempDir, testutil.JsonLog(testutil.NewJsonLogKeys()))
+	tempLog, err := testutil.CreateTempDirAndFile(tempDir, "test_common_flags_temp_log", testutil.JsonLog(testutil.NewJsonLogKeys()))
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	tempConfig, err := testutil.CreateTempDirAndFile(tempDir, testutil.ConfigFile())
+	tempConfig, err := testutil.CreateTempDirAndFile(tempDir, "test_common_flags_temp_config", testutil.ConfigFile())
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	tempPos, err := testutil.CreateTempDirAndFile(tempDir, "")
+	tempPos, err := testutil.CreateTempDirAndFile(tempDir, "test_common_flags_temp_pos", "")
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	tempDump, err := testutil.CreateTempDirAndFile(tempDir, "")
+	tempDump, err := testutil.CreateTempDirAndFile(tempDir, "test_common_flags_temp_dump", "")
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/cmd/alp/cmd/count.go b/cmd/alp/cmd/count.go
index 02616a1..4d737d9 100644
--- a/cmd/alp/cmd/count.go
+++ b/cmd/alp/cmd/count.go
@@ -3,53 +3,41 @@ package cmd
 import (
 	"os"
 
+	"github.com/tkuchiki/alp/options"
+
 	"github.com/spf13/cobra"
 	"github.com/tkuchiki/alp/counter"
-	"github.com/tkuchiki/alp/helpers"
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/parsers"
 )
 
-func NewCountCmd() *cobra.Command {
+func NewCountCmd(commandFlags *flags) *cobra.Command {
 	var countCmd = &cobra.Command{
 		Use:   "count",
 		Short: "Count by log entries",
 		Long:  `Count by log entries`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			file, err := cmd.PersistentFlags().GetString("file")
+			opts, err := commandFlags.createCountOptions(cmd)
 			if err != nil {
 				return err
 			}
 
-			reverse, err := cmd.PersistentFlags().GetBool("reverse")
+			// TODO: start
+			// Remove these after implementing `alp (json|ltsv|regex) count`.
+			pattern, err := cmd.PersistentFlags().GetString("pattern")
 			if err != nil {
 				return err
 			}
 
-			pattern, err := cmd.PersistentFlags().GetString("pattern")
+			format, err := cmd.PersistentFlags().GetString("format")
 			if err != nil {
 				return err
 			}
 
-			opts := options.NewOptions()
-
 			opts = options.SetOptions(opts,
-				options.File(file),
-				options.Reverse(reverse),
 				options.Pattern(pattern),
+				options.Format(format),
 			)
-
-			format, err := cmd.PersistentFlags().GetString("format")
-			if err != nil {
-				return err
-			}
-
-			keysStr, err := cmd.PersistentFlags().GetString("keys")
-			if err != nil {
-				return err
-			}
-
-			keys := helpers.SplitCSV(keysStr)
+			// TODO: end
 
 			cnter := counter.NewCounter(os.Stdout, os.Stderr, opts.Reverse)
 
@@ -81,18 +69,21 @@ func NewCountCmd() *cobra.Command {
 
 			cnter.SetParser(parser)
 
-			err = cnter.CountAndPrint(keys)
+			err = cnter.CountAndPrint(opts.Count.Keys)
 
 			return err
 		},
 	}
 
+	commandFlags.defineCountOptions(countCmd)
+
+	// TODO: Remove these after implementing `alp (json|ltsv|regex) count`.
+	countCmd.PersistentFlags().StringP("pattern", "", options.DefaultPatternOption, "Regular expressions pattern matching the log")
 	countCmd.PersistentFlags().StringP("format", "", "json", "Log format (json,ltsv,regexp)")
-	countCmd.PersistentFlags().StringP("pattern", "", options.DefaultPatternOption, "Regular expressions pattern matching the log (only use with --format=regexp)")
-	countCmd.PersistentFlags().StringP("file", "", "", "The access log file")
-	countCmd.PersistentFlags().BoolP("reverse", "r", false, "Sort results in reverse order")
-	countCmd.PersistentFlags().StringP("keys", "", "", "Log key names (comma separated)")
-	countCmd.MarkPersistentFlagRequired("keys")
+
+	countCmd.Flags().SortFlags = false
+	countCmd.PersistentFlags().SortFlags = false
+	countCmd.InheritedFlags().SortFlags = false
 
 	return countCmd
 }
diff --git a/cmd/alp/cmd/diff.go b/cmd/alp/cmd/diff.go
index 8b0367e..4968352 100644
--- a/cmd/alp/cmd/diff.go
+++ b/cmd/alp/cmd/diff.go
@@ -4,32 +4,17 @@ import (
 	"os"
 
 	"github.com/spf13/cobra"
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/stats"
 )
 
-func NewDiffCmd() *cobra.Command {
+func NewDiffCmd(commandFlags *flags) *cobra.Command {
 	diffCmd := &cobra.Command{
 		Use:   "diff <from> <to>",
 		Args:  cobra.ExactArgs(2),
 		Short: "Show the difference between the two profile results",
 		Long:  `Show the difference between the two profile results`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			sortOptions := stats.NewSortOptions()
-			var opts *options.Options
-
-			config, err := cmd.PersistentFlags().GetString("config")
-			if err != nil {
-				return err
-			}
-
-			if config != "" {
-				bindCommonFlags(cmd)
-				opts, err = createOptionsFromConfig(cmd, sortOptions, config)
-			} else {
-				opts, err = createCommonOptionsFromFlags(cmd, sortOptions)
-			}
-
+			opts, err := commandFlags.createDiffOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -45,7 +30,7 @@ func NewDiffCmd() *cobra.Command {
 			}
 
 			sts.SetOptions(opts)
-			sts.SetSortOptions(sortOptions)
+			sts.SetSortOptions(commandFlags.sortOptions)
 
 			printOptions := stats.NewPrintOptions(opts.NoHeaders, opts.ShowFooters, opts.DecodeUri, opts.PaginationLimit)
 			printer := stats.NewPrinter(os.Stdout, opts.Output, opts.Format, opts.Percentiles, printOptions)
@@ -72,7 +57,7 @@ func NewDiffCmd() *cobra.Command {
 			}
 
 			toSts.SetOptions(opts)
-			toSts.SetSortOptions(sortOptions)
+			toSts.SetSortOptions(commandFlags.sortOptions)
 
 			tof, err := os.Open(to)
 			if err != nil {
@@ -92,7 +77,11 @@ func NewDiffCmd() *cobra.Command {
 		},
 	}
 
-	defineOptions(diffCmd)
+	commandFlags.defineDiffOptions(diffCmd)
+
+	diffCmd.Flags().SortFlags = false
+	diffCmd.PersistentFlags().SortFlags = false
+	diffCmd.InheritedFlags().SortFlags = false
 
 	return diffCmd
 }
diff --git a/cmd/alp/cmd/flags.go b/cmd/alp/cmd/flags.go
new file mode 100644
index 0000000..b2e3dcc
--- /dev/null
+++ b/cmd/alp/cmd/flags.go
@@ -0,0 +1,921 @@
+package cmd
+
+import (
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
+	"github.com/tkuchiki/alp/helpers"
+	"github.com/tkuchiki/alp/options"
+	"github.com/tkuchiki/alp/stats"
+)
+
+const (
+	flagConfig                  = "config"
+	flagFile                    = "file"
+	flagDump                    = "dump"
+	flagLoad                    = "load"
+	flagFormat                  = "format"
+	flagSort                    = "sort"
+	flagReverse                 = "reverse"
+	flagNoHeaders               = "noheaders"
+	flagShowFooters             = "show-footers"
+	flagLimit                   = "limit"
+	flagOutput                  = "output"
+	flagQueryString             = "query-string"
+	flagQueryStringIgnoreValues = "qs-ignore-values"
+	flagLocation                = "location"
+	flagDecodeUri               = "decode-uri"
+	flagMatchingGroups          = "matching-groups"
+	flagFilters                 = "filters"
+	flagPositionFile            = "pos"
+	flagNoSavePositionFile      = "nosave-pos"
+	flagPercentiles             = "percentiles"
+	flagPage                    = "page"
+
+	// json
+	flagJSONUriKey       = "uri-key"
+	flagJSONMethodKey    = "method-key"
+	flagJSONTimeKey      = "time-key"
+	flagJSONRestimeKey   = "restime-key"
+	flagJSONReqtimeKey   = "reqtime-key"
+	flagJSONBodyBytesKey = "body-bytes-key"
+	flagJSONStatusKey    = "status-key"
+
+	// ltsv
+	flagLTSVUriLabel     = "uri-label"
+	flagLTSVMethodLabel  = "method-label"
+	flagLTSVTimeLabel    = "time-label"
+	flagLTSVApptimeLabel = "apptime-label"
+	flagLTSVReqtimeLabel = "reqtime-label"
+	flagLTSVSizeLabel    = "size-label"
+	flagLTSVStatusLabel  = "status-label"
+
+	// regexp
+	flagRegexpPattern         = "pattern"
+	flagRegexpUriSubexp       = "uri-subexp"
+	flagRegexpMethodSubexp    = "method-subexp"
+	flagRegexpTimeSubexp      = "time-subexp"
+	flagRegexpRestimeSubexp   = "restime-subexp"
+	flagRegexpReqtimeSubexp   = "reqtime-subexp"
+	flagRegexpBodyBytesSubexp = "body-bytes-subexp"
+	flagRegexpStatusSubexp    = "status-subexp"
+
+	// pcap
+	flagPcapPcapServerIP   = "pcap-server-ip"
+	flagPcapPcapServerPort = "pcap-server-port"
+
+	// count
+	flagCountKeys = "keys"
+)
+
+type flags struct {
+	config      string
+	sortOptions *stats.SortOptions
+}
+
+func newFlags() *flags {
+	return &flags{
+		sortOptions: stats.NewSortOptions(),
+	}
+}
+
+func (f *flags) defineConfig(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringVar(&f.config, flagConfig, "", "The configuration file")
+}
+
+func (f *flags) defineFile(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagFile, "", "", "The access log file")
+}
+
+func (f *flags) defineDump(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagDump, "", "", "Dump profiled data as YAML")
+}
+
+func (f *flags) defineLoad(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLoad, "", "", "Load the profiled YAML data")
+}
+
+func (f *flags) defineFormat(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagFormat, "", options.DefaultFormatOption, "The output format (table, markdown, tsv, csv and html)")
+}
+
+func (f *flags) defineSort(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagSort, "", options.DefaultSortOption, "Output the results in sorted order")
+}
+
+func (f *flags) defineReverse(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagReverse, "r", false, "Sort results in reverse order")
+}
+
+func (f *flags) defineNoHeaders(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagNoHeaders, "", false, "Output no header line at all (only --format=tsv, csv)")
+}
+
+func (f *flags) defineShowFooters(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagShowFooters, "", false, "Output footer line at all (only --format=table, markdown)")
+}
+
+func (f *flags) defineLimit(cmd *cobra.Command) {
+	cmd.PersistentFlags().IntP(flagLimit, "", options.DefaultLimitOption, "The maximum number of results to display")
+}
+
+func (f *flags) defineOutput(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagOutput, "o", options.DefaultOutputOption, "Specifies the results to display, separated by commas")
+}
+
+func (f *flags) defineQueryString(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagQueryString, "q", false, "Include the URI query string")
+}
+
+func (f *flags) defineQueryStringIgnoreValues(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagQueryStringIgnoreValues, "", false, "Ignore the value of the query string. Replace all values with xxx (only use with -q)")
+}
+
+func (f *flags) defineLocation(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLocation, "", options.DefaultLocationOption, "Location name for the timezone")
+}
+
+func (f *flags) defineDecodeUri(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagDecodeUri, "", false, "Decode the URI")
+}
+
+func (f *flags) defineMatchingGroups(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagMatchingGroups, "m", "", "Specifies Query matching groups separated by commas")
+}
+
+func (f *flags) defineFilters(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagFilters, "f", "", "Only the logs are profiled that match the conditions")
+}
+
+func (f *flags) definePositionFile(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagPositionFile, "", "", "The position file")
+}
+
+func (f *flags) defineNoSavePositionFile(cmd *cobra.Command) {
+	cmd.PersistentFlags().BoolP(flagNoSavePositionFile, "", false, "Do not save position file")
+}
+
+func (f *flags) definePercentiles(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagPercentiles, "", "", "Specifies the percentiles separated by commas")
+}
+
+func (f *flags) definePage(cmd *cobra.Command) {
+	cmd.PersistentFlags().IntP(flagPage, "", options.DefaultPaginationLimit, "Number of pages of pagination")
+}
+
+func (f *flags) defineJSONUriKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONUriKey, "", options.DefaultUriKeyOption, "Change the uri key")
+}
+
+func (f *flags) defineJSONMethodKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONMethodKey, "", options.DefaultMethodKeyOption, "Change the method key")
+}
+
+func (f *flags) defineJSONTimeKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONTimeKey, "", options.DefaultTimeKeyOption, "Change the time key")
+}
+
+func (f *flags) defineJSONRestimeKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONRestimeKey, "", options.DefaultResponseTimeKeyOption, "Change the response_time key")
+}
+
+func (f *flags) defineJSONReqtimeKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONReqtimeKey, "", options.DefaultRequestTimeKeyOption, "Change the request_time key")
+}
+
+func (f *flags) defineJSONBodyBytesKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONBodyBytesKey, "", options.DefaultBodyBytesKeyOption, "Change the body_bytes key")
+}
+
+func (f *flags) defineJSONStatusKey(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagJSONStatusKey, "", options.DefaultStatusKeyOption, "Change the status key")
+}
+
+func (f *flags) defineLTSVUriLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVUriLabel, "", options.DefaultUriLabelOption, "Change the uri label")
+}
+
+func (f *flags) defineLTSVMethodLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVMethodLabel, "", options.DefaultMethodLabelOption, "Change the method label")
+}
+
+func (f *flags) defineLTSVTimeLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVTimeLabel, "", options.DefaultTimeLabelOption, "Change the time label")
+}
+
+func (f *flags) defineLTSVApptimeLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVApptimeLabel, "", options.DefaultApptimeLabelOption, "Change the apptime label")
+}
+
+func (f *flags) defineLTSVReqtimeLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVReqtimeLabel, "", options.DefaultReqtimeLabelOption, "Change the reqtime label")
+}
+
+func (f *flags) defineLTSVSizeLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVSizeLabel, "", options.DefaultSizeLabelOption, "Change the size label")
+}
+
+func (f *flags) defineLTSVStatusLabel(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagLTSVStatusLabel, "", options.DefaultStatusLabelOption, "Change the status label")
+}
+
+func (f *flags) defineRegexpPattern(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpPattern, "", options.DefaultPatternOption, "Regular expressions pattern matching the log")
+}
+
+func (f *flags) defineRegexpUriSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpUriSubexp, "", options.DefaultUriSubexpOption, "Change the uri sub expression")
+}
+
+func (f *flags) defineRegexpMethodSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpMethodSubexp, "", options.DefaultMethodSubexpOption, "Change the method sub expression")
+}
+
+func (f *flags) defineRegexpTimeSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpTimeSubexp, "", options.DefaultTimeSubexpOption, "Change the time sub expression")
+}
+
+func (f *flags) defineRegexpRestimeSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpRestimeSubexp, "", options.DefaultResponseTimeSubexpOption, "Change the response_time sub expression")
+}
+
+func (f *flags) defineRegexpReqtimeSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpReqtimeSubexp, "", options.DefaultRequestTimeSubexpOption, "Change the request_time sub expression")
+}
+
+func (f *flags) defineRegexpBodyBytesSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpBodyBytesSubexp, "", options.DefaultBodyBytesSubexpOption, "Change the body_bytes sub expression")
+}
+
+func (f *flags) defineRegexpStatusSubexp(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagRegexpStatusSubexp, "", options.DefaultStatusSubexpOption, "Change the status sub expression")
+}
+
+func (f *flags) definePcapPcapServerIP(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringSliceP(flagPcapPcapServerIP, "", []string{options.DefaultPcapServerIPsOption[0]}, "HTTP server IP address of the captured packets")
+}
+
+func (f *flags) definePcapPcapServerPort(cmd *cobra.Command) {
+	cmd.PersistentFlags().Uint16P(flagPcapPcapServerPort, "", options.DefaultPcapServerPortOption, "HTTP server TCP port of the captured packets")
+}
+
+func (f *flags) defineCountKeys(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringP(flagCountKeys, "", "", "Log key names (comma separated)")
+	cmd.MarkPersistentFlagRequired(flagCountKeys)
+}
+
+func (f *flags) defineGlobalOptions(cmd *cobra.Command) {
+	f.defineConfig(cmd)
+}
+
+func (f *flags) defineProfileOptions(cmd *cobra.Command) {
+	f.defineFile(cmd)
+	f.defineDump(cmd)
+	f.defineLoad(cmd)
+	f.defineFormat(cmd)
+	f.defineSort(cmd)
+	f.defineReverse(cmd)
+	f.defineNoHeaders(cmd)
+	f.defineShowFooters(cmd)
+	f.defineLimit(cmd)
+	f.defineOutput(cmd)
+	f.defineQueryString(cmd)
+	f.defineQueryStringIgnoreValues(cmd)
+	f.defineLocation(cmd)
+	f.defineDecodeUri(cmd)
+	f.defineMatchingGroups(cmd)
+	f.defineFilters(cmd)
+	f.definePositionFile(cmd)
+	f.defineNoSavePositionFile(cmd)
+	f.definePercentiles(cmd)
+	f.definePage(cmd)
+}
+
+func (f *flags) defineJSONOptions(cmd *cobra.Command) {
+	f.defineJSONUriKey(cmd)
+	f.defineJSONMethodKey(cmd)
+	f.defineJSONTimeKey(cmd)
+	f.defineJSONRestimeKey(cmd)
+	f.defineJSONReqtimeKey(cmd)
+	f.defineJSONBodyBytesKey(cmd)
+	f.defineJSONStatusKey(cmd)
+}
+
+func (f *flags) defineLTSVOptions(cmd *cobra.Command) {
+	f.defineLTSVUriLabel(cmd)
+	f.defineLTSVMethodLabel(cmd)
+	f.defineLTSVTimeLabel(cmd)
+	f.defineLTSVApptimeLabel(cmd)
+	f.defineLTSVReqtimeLabel(cmd)
+	f.defineLTSVSizeLabel(cmd)
+	f.defineLTSVStatusLabel(cmd)
+}
+
+func (f *flags) defineRegexpOptions(cmd *cobra.Command) {
+	f.defineRegexpPattern(cmd)
+	f.defineRegexpUriSubexp(cmd)
+	f.defineRegexpMethodSubexp(cmd)
+	f.defineRegexpTimeSubexp(cmd)
+	f.defineRegexpRestimeSubexp(cmd)
+	f.defineRegexpReqtimeSubexp(cmd)
+	f.defineRegexpBodyBytesSubexp(cmd)
+	f.defineRegexpStatusSubexp(cmd)
+}
+
+func (f *flags) definePcapOptions(cmd *cobra.Command) {
+	f.definePcapPcapServerIP(cmd)
+	f.definePcapPcapServerPort(cmd)
+}
+
+func (f *flags) defineCountOptions(cmd *cobra.Command) {
+	f.defineFile(cmd)
+	f.defineReverse(cmd)
+	f.defineCountKeys(cmd)
+}
+
+func (f *flags) defineDiffOptions(cmd *cobra.Command) {
+	f.defineFormat(cmd)
+	f.defineSort(cmd)
+	f.defineReverse(cmd)
+	f.defineNoHeaders(cmd)
+	f.defineShowFooters(cmd)
+	f.defineLimit(cmd)
+	f.defineOutput(cmd)
+	f.defineQueryString(cmd)
+	f.defineQueryStringIgnoreValues(cmd)
+	f.defineLocation(cmd)
+	f.defineDecodeUri(cmd)
+	f.defineMatchingGroups(cmd)
+	f.defineFilters(cmd)
+	f.definePercentiles(cmd)
+	f.definePage(cmd)
+}
+
+func (f *flags) bindFlags(cmd *cobra.Command) {
+	viper.BindPFlag("file", cmd.PersistentFlags().Lookup(flagFile))
+	viper.BindPFlag("dump", cmd.PersistentFlags().Lookup(flagDump))
+	viper.BindPFlag("load", cmd.PersistentFlags().Lookup(flagLoad))
+	viper.BindPFlag("sort", cmd.PersistentFlags().Lookup(flagSort))
+	viper.BindPFlag("reverse", cmd.PersistentFlags().Lookup(flagReverse))
+	viper.BindPFlag("query_string", cmd.PersistentFlags().Lookup(flagQueryString))
+	viper.BindPFlag("query_string_ignore_values", cmd.PersistentFlags().Lookup(flagQueryStringIgnoreValues))
+	viper.BindPFlag("decode_uri", cmd.PersistentFlags().Lookup(flagDecodeUri))
+	viper.BindPFlag("format", cmd.PersistentFlags().Lookup(flagFormat))
+	viper.BindPFlag("noheaders", cmd.PersistentFlags().Lookup(flagNoHeaders))
+	viper.BindPFlag("show_footers", cmd.PersistentFlags().Lookup(flagShowFooters))
+	viper.BindPFlag("limit", cmd.PersistentFlags().Lookup(flagLimit))
+	viper.BindPFlag("matching_groups", cmd.PersistentFlags().Lookup(flagMatchingGroups))
+	viper.BindPFlag("filters", cmd.PersistentFlags().Lookup(flagFilters))
+	viper.BindPFlag("pos_file", cmd.PersistentFlags().Lookup(flagPositionFile))
+	viper.BindPFlag("nosave_pos", cmd.PersistentFlags().Lookup(flagNoSavePositionFile))
+	viper.BindPFlag("location", cmd.PersistentFlags().Lookup(flagLocation))
+	viper.BindPFlag("output", cmd.PersistentFlags().Lookup(flagOutput))
+	viper.BindPFlag("pagenation_limit", cmd.PersistentFlags().Lookup(flagPage))
+
+	// json
+	viper.BindPFlag("json.uri_key", cmd.PersistentFlags().Lookup(flagJSONUriKey))
+	viper.BindPFlag("json.method_key", cmd.PersistentFlags().Lookup(flagJSONMethodKey))
+	viper.BindPFlag("json.time_key", cmd.PersistentFlags().Lookup(flagJSONTimeKey))
+	viper.BindPFlag("json.restime_key", cmd.PersistentFlags().Lookup(flagJSONRestimeKey))
+	viper.BindPFlag("json.reqtime_key", cmd.PersistentFlags().Lookup(flagJSONReqtimeKey))
+	viper.BindPFlag("json.body_bytes_key", cmd.PersistentFlags().Lookup(flagJSONBodyBytesKey))
+	viper.BindPFlag("json.status_key", cmd.PersistentFlags().Lookup(flagJSONStatusKey))
+
+	// ltsv
+	viper.BindPFlag("ltsv.uri_label", cmd.PersistentFlags().Lookup(flagLTSVUriLabel))
+	viper.BindPFlag("ltsv.method_label", cmd.PersistentFlags().Lookup(flagLTSVMethodLabel))
+	viper.BindPFlag("ltsv.time_label", cmd.PersistentFlags().Lookup(flagLTSVTimeLabel))
+	viper.BindPFlag("ltsv.apptime_label", cmd.PersistentFlags().Lookup(flagLTSVApptimeLabel))
+	viper.BindPFlag("ltsv.reqtime_label", cmd.PersistentFlags().Lookup(flagLTSVReqtimeLabel))
+	viper.BindPFlag("ltsv.size_label", cmd.PersistentFlags().Lookup(flagLTSVSizeLabel))
+	viper.BindPFlag("ltsv.status_label", cmd.PersistentFlags().Lookup(flagLTSVStatusLabel))
+
+	// regexp
+	viper.BindPFlag("regexp.pattern", cmd.PersistentFlags().Lookup(flagRegexpPattern))
+	viper.BindPFlag("regexp.uri_subexp", cmd.PersistentFlags().Lookup(flagRegexpUriSubexp))
+	viper.BindPFlag("regexp.method_subexp", cmd.PersistentFlags().Lookup(flagRegexpMethodSubexp))
+	viper.BindPFlag("regexp.time_subexp", cmd.PersistentFlags().Lookup(flagRegexpTimeSubexp))
+	viper.BindPFlag("regexp.restime_subexp", cmd.PersistentFlags().Lookup(flagRegexpRestimeSubexp))
+	viper.BindPFlag("regexp.reqtime_subexp", cmd.PersistentFlags().Lookup(flagRegexpReqtimeSubexp))
+	viper.BindPFlag("regexp.body_bytes_subexp", cmd.PersistentFlags().Lookup(flagRegexpBodyBytesSubexp))
+	viper.BindPFlag("regexp.status_subexp", cmd.PersistentFlags().Lookup(flagRegexpStatusSubexp))
+
+	// pcap
+	viper.BindPFlag("pcap.server_port", cmd.PersistentFlags().Lookup(flagPcapPcapServerPort))
+
+	// count
+	viper.BindPFlag("count.keys", cmd.PersistentFlags().Lookup(flagCountKeys))
+}
+
+func (f *flags) createOptionsFromConfig(cmd *cobra.Command) (*options.Options, error) {
+	opts := options.NewOptions()
+	viper.SetConfigFile(f.config)
+	viper.SetConfigType("yaml")
+
+	// Start workaround
+	// viper seems to merge slices, so we'll set empty slice and overwrite it manually.
+	opts.Percentiles = []int{}
+	opts.Pcap.ServerIPs = []string{}
+
+	if err := viper.ReadInConfig(); err != nil {
+		return nil, err
+	}
+
+	if err := viper.Unmarshal(opts); err != nil {
+		return nil, err
+	}
+
+	if len(opts.Percentiles) == 0 {
+		opts.Percentiles = options.DefaultPercentilesOption
+	}
+
+	if len(opts.Pcap.ServerIPs) == 0 {
+		opts.Pcap.ServerIPs = []string{options.DefaultPcapServerIPsOption[0]}
+	}
+	// End workaround
+
+	percentilesFlag := cmd.PersistentFlags().Lookup(flagPercentiles)
+	if percentilesFlag != nil && percentilesFlag.Changed {
+		ps := cmd.PersistentFlags().Lookup(flagPercentiles).Value.String()
+		var percentiles []int
+		var err error
+		if ps != "" {
+			percentiles, err = helpers.SplitCSVIntoInts(ps)
+			if err != nil {
+				return nil, err
+			}
+
+			if err = helpers.ValidatePercentiles(percentiles); err != nil {
+				return nil, err
+			}
+		}
+		opts.Percentiles = percentiles
+	}
+
+	srvIPFlag := cmd.PersistentFlags().Lookup(flagPcapPcapServerIP)
+	if srvIPFlag != nil && srvIPFlag.Changed {
+		ips := cmd.PersistentFlags().Lookup(flagPcapPcapServerIP).Value.String()
+		opts.Pcap.ServerIPs = helpers.SplitCSV(ips)
+	}
+
+	if err := f.sortOptions.SetAndValidate(opts.Sort); err != nil {
+		return nil, err
+	}
+	opts.Sort = f.sortOptions.SortType()
+
+	return opts, nil
+}
+
+func (f *flags) setOptions(cmd *cobra.Command, opts *options.Options, flags []string) (*options.Options, error) {
+	for _, flag := range flags {
+		switch flag {
+		case flagFile:
+			file, err := cmd.PersistentFlags().GetString(flagFile)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.File(file))
+		case flagDump:
+			dump, err := cmd.PersistentFlags().GetString(flagDump)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Dump(dump))
+		case flagLoad:
+			load, err := cmd.PersistentFlags().GetString(flagLoad)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Load(load))
+		case flagFormat:
+			format, err := cmd.PersistentFlags().GetString(flagFormat)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Format(format))
+		case flagSort:
+			sort, err := cmd.PersistentFlags().GetString(flagSort)
+			if err != nil {
+				return nil, err
+			}
+
+			err = f.sortOptions.SetAndValidate(sort)
+			if err != nil {
+				return nil, err
+			}
+
+			opts = options.SetOptions(opts, options.Sort(sort))
+		case flagReverse:
+			reverse, err := cmd.PersistentFlags().GetBool(flagReverse)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Reverse(reverse))
+		case flagNoHeaders:
+			noHeaders, err := cmd.PersistentFlags().GetBool(flagNoHeaders)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.NoHeaders(noHeaders))
+		case flagShowFooters:
+			showFooters, err := cmd.PersistentFlags().GetBool(flagShowFooters)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.ShowFooters(showFooters))
+		case flagLimit:
+			limit, err := cmd.PersistentFlags().GetInt(flagLimit)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Limit(limit))
+		case flagOutput:
+			output, err := cmd.PersistentFlags().GetString(flagOutput)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Output(output))
+		case flagQueryString:
+			queryString, err := cmd.PersistentFlags().GetBool(flagQueryString)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.QueryString(queryString))
+		case flagQueryStringIgnoreValues:
+			queryStringIgnoreValues, err := cmd.PersistentFlags().GetBool(flagQueryStringIgnoreValues)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.QueryStringIgnoreValues(queryStringIgnoreValues))
+		case flagDecodeUri:
+			decodeUri, err := cmd.PersistentFlags().GetBool(flagDecodeUri)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.DecodeUri(decodeUri))
+		case flagLocation:
+			location, err := cmd.PersistentFlags().GetString(flagLocation)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Location(location))
+		case flagMatchingGroups:
+			matchingGroups, err := cmd.PersistentFlags().GetString(flagMatchingGroups)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.CSVGroups(matchingGroups))
+		case flagFilters:
+			filters, err := cmd.PersistentFlags().GetString(flagFilters)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.Filters(filters))
+		case flagPositionFile:
+			pos, err := cmd.PersistentFlags().GetString(flagPositionFile)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.PosFile(pos))
+		case flagNoSavePositionFile:
+			noSavePos, err := cmd.PersistentFlags().GetBool(flagNoSavePositionFile)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.NoSavePos(noSavePos))
+		case flagPercentiles:
+			ps, err := cmd.PersistentFlags().GetString(flagPercentiles)
+			if err != nil {
+				return nil, err
+			}
+
+			var percentiles []int
+			if ps != "" {
+				percentiles, err = helpers.SplitCSVIntoInts(ps)
+				if err != nil {
+					return nil, err
+				}
+
+				if err = helpers.ValidatePercentiles(percentiles); err != nil {
+					return nil, err
+				}
+			}
+			opts = options.SetOptions(opts, options.Percentiles(percentiles))
+		case flagPage:
+			paginationLimit, err := cmd.PersistentFlags().GetInt(flagPage)
+			if err != nil {
+				return nil, err
+			}
+			opts = options.SetOptions(opts, options.PaginationLimit(paginationLimit))
+		}
+	}
+
+	return opts, nil
+}
+
+func (f *flags) setProfileOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	_flags := []string{
+		flagConfig,
+		flagFile,
+		flagDump,
+		flagLoad,
+		flagFormat,
+		flagSort,
+		flagReverse,
+		flagNoHeaders,
+		flagShowFooters,
+		flagLimit,
+		flagOutput,
+		flagQueryString,
+		flagQueryStringIgnoreValues,
+		flagLocation,
+		flagDecodeUri,
+		flagMatchingGroups,
+		flagFilters,
+		flagPositionFile,
+		flagNoSavePositionFile,
+		flagPercentiles,
+		flagPage,
+	}
+
+	return f.setOptions(cmd, opts, _flags)
+}
+
+func (f *flags) setJSONOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	uriKey, err := cmd.PersistentFlags().GetString(flagJSONUriKey)
+	if err != nil {
+		return nil, err
+	}
+
+	methodKey, err := cmd.PersistentFlags().GetString(flagJSONMethodKey)
+	if err != nil {
+		return nil, err
+	}
+
+	timeKey, err := cmd.PersistentFlags().GetString(flagJSONTimeKey)
+	if err != nil {
+		return nil, err
+	}
+
+	responseTimeKey, err := cmd.PersistentFlags().GetString(flagJSONRestimeKey)
+	if err != nil {
+		return nil, err
+	}
+
+	requestTimeKey, err := cmd.PersistentFlags().GetString(flagJSONReqtimeKey)
+	if err != nil {
+		return nil, err
+	}
+
+	bodyBytesKey, err := cmd.PersistentFlags().GetString(flagJSONBodyBytesKey)
+	if err != nil {
+		return nil, err
+	}
+
+	statusKey, err := cmd.PersistentFlags().GetString(flagJSONStatusKey)
+	if err != nil {
+		return nil, err
+	}
+
+	return options.SetOptions(opts,
+		options.UriKey(uriKey),
+		options.MethodKey(methodKey),
+		options.TimeKey(timeKey),
+		options.ResponseTimeKey(responseTimeKey),
+		options.RequestTimeKey(requestTimeKey),
+		options.BodyBytesKey(bodyBytesKey),
+		options.StatusKey(statusKey),
+	), nil
+}
+
+func (f *flags) setLTSVOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	uriLabel, err := cmd.PersistentFlags().GetString(flagLTSVUriLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	methodLabel, err := cmd.PersistentFlags().GetString(flagLTSVMethodLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	timeLabel, err := cmd.PersistentFlags().GetString(flagLTSVTimeLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	appTimeLabel, err := cmd.PersistentFlags().GetString(flagLTSVApptimeLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	reqTimeLabel, err := cmd.PersistentFlags().GetString(flagLTSVReqtimeLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	sizeLabel, err := cmd.PersistentFlags().GetString(flagLTSVSizeLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	statusLabel, err := cmd.PersistentFlags().GetString(flagLTSVStatusLabel)
+	if err != nil {
+		return nil, err
+	}
+
+	return options.SetOptions(opts,
+		options.UriLabel(uriLabel),
+		options.MethodLabel(methodLabel),
+		options.TimeLabel(timeLabel),
+		options.ApptimeLabel(appTimeLabel),
+		options.ReqtimeLabel(reqTimeLabel),
+		options.SizeLabel(sizeLabel),
+		options.StatusLabel(statusLabel),
+	), nil
+}
+
+func (f *flags) setRegexpOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	pattern, err := cmd.PersistentFlags().GetString(flagRegexpPattern)
+	if err != nil {
+		return nil, err
+	}
+
+	uriSubexp, err := cmd.PersistentFlags().GetString(flagRegexpUriSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	methodSubexp, err := cmd.PersistentFlags().GetString(flagRegexpMethodSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	timeSubexp, err := cmd.PersistentFlags().GetString(flagRegexpTimeSubexp)
+	if err != nil {
+		return nil, err
+	}
+	restimeSubexp, err := cmd.PersistentFlags().GetString(flagRegexpRestimeSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	reqtimeSubexp, err := cmd.PersistentFlags().GetString(flagRegexpReqtimeSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	bodyBytesSubexp, err := cmd.PersistentFlags().GetString(flagRegexpBodyBytesSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	statusSubexp, err := cmd.PersistentFlags().GetString(flagRegexpStatusSubexp)
+	if err != nil {
+		return nil, err
+	}
+
+	return options.SetOptions(opts,
+		options.Pattern(pattern),
+		options.UriSubexp(uriSubexp),
+		options.MethodSubexp(methodSubexp),
+		options.TimeSubexp(timeSubexp),
+		options.ResponseTimeSubexp(restimeSubexp),
+		options.RequestTimeSubexp(reqtimeSubexp),
+		options.BodyBytesSubexp(bodyBytesSubexp),
+		options.StatusSubexp(statusSubexp),
+	), nil
+}
+
+func (f *flags) setPcapOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	serverIPs, err := cmd.PersistentFlags().GetStringSlice(flagPcapPcapServerIP)
+	if err != nil {
+		return nil, err
+	}
+
+	serverPort, err := cmd.PersistentFlags().GetUint16(flagPcapPcapServerPort)
+	if err != nil {
+		return nil, err
+	}
+
+	return options.SetOptions(opts,
+		options.PcapServerIPs(serverIPs),
+		options.PcapServerPort(serverPort),
+	), nil
+}
+
+func (f *flags) setCountOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	keys, err := cmd.PersistentFlags().GetString(flagCountKeys)
+	if err != nil {
+		return nil, err
+	}
+
+	return options.SetOptions(opts,
+		options.CountKeys(helpers.SplitCSV(keys)),
+	), nil
+}
+
+func (f *flags) setDiffOptions(cmd *cobra.Command, opts *options.Options) (*options.Options, error) {
+	_flags := []string{
+		flagFormat,
+		flagSort,
+		flagReverse,
+		flagNoHeaders,
+		flagShowFooters,
+		flagLimit,
+		flagOutput,
+		flagQueryString,
+		flagQueryStringIgnoreValues,
+		flagLocation,
+		flagDecodeUri,
+		flagMatchingGroups,
+		flagFilters,
+		flagPercentiles,
+		flagPage,
+	}
+
+	return f.setOptions(cmd, opts, _flags)
+}
+
+func (f *flags) createJSONOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	opts, err := f.setProfileOptions(cmd, options.NewOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	return f.setJSONOptions(cmd, opts)
+}
+
+func (f *flags) createLTSVOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	opts, err := f.setProfileOptions(cmd, options.NewOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	return f.setLTSVOptions(cmd, opts)
+}
+
+func (f *flags) createRegexpOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	opts, err := f.setProfileOptions(cmd, options.NewOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	return f.setRegexpOptions(cmd, opts)
+}
+
+func (f *flags) createPcapOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	opts, err := f.setProfileOptions(cmd, options.NewOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	return f.setPcapOptions(cmd, opts)
+}
+
+func (f *flags) createCountOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	flags := []string{
+		flagFile,
+		flagReverse,
+	}
+
+	opts, err := f.setOptions(cmd, options.NewOptions(), flags)
+	if err != nil {
+		return nil, err
+	}
+
+	return f.setCountOptions(cmd, opts)
+}
+
+func (f *flags) createDiffOptions(cmd *cobra.Command) (*options.Options, error) {
+	if f.config != "" {
+		f.bindFlags(cmd)
+		return f.createOptionsFromConfig(cmd)
+	}
+
+	return f.setDiffOptions(cmd, options.NewOptions())
+}
diff --git a/cmd/alp/cmd/flags_test.go b/cmd/alp/cmd/flags_test.go
new file mode 100644
index 0000000..d9e8ad1
--- /dev/null
+++ b/cmd/alp/cmd/flags_test.go
@@ -0,0 +1,135 @@
+package cmd
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/spf13/viper"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/tkuchiki/alp/internal/testutil"
+	"github.com/tkuchiki/alp/options"
+)
+
+func Test_createOptionsFromConfig(t *testing.T) {
+	viper.Reset()
+	rootCmd := NewRootCmd("test")
+	flags := newFlags()
+
+	flags.defineProfileOptions(rootCmd)
+	flags.defineJSONOptions(rootCmd)
+	flags.defineLTSVOptions(rootCmd)
+	flags.defineRegexpOptions(rootCmd)
+	flags.definePcapOptions(rootCmd)
+	flags.defineCountKeys(rootCmd)
+
+	tempDir := t.TempDir()
+	sort := "max"
+	dummyOpts := testutil.DummyOptions(sort)
+
+	var err error
+	flags.config, err = testutil.CreateTempDirAndFile(tempDir, "test_create_options_from_config_config", testutil.DummyConfigFile(sort, dummyOpts))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var opts *options.Options
+	opts, err = flags.createOptionsFromConfig(rootCmd)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if diff := cmp.Diff(dummyOpts, opts); diff != "" {
+		t.Errorf("%s", diff)
+	}
+}
+
+func Test_createOptionsFromConfig_overwrite(t *testing.T) {
+	rootCmd := NewRootCmd("test")
+	flags := newFlags()
+
+	flags.defineProfileOptions(rootCmd)
+	flags.defineJSONOptions(rootCmd)
+	flags.defineLTSVOptions(rootCmd)
+	flags.defineRegexpOptions(rootCmd)
+	flags.definePcapOptions(rootCmd)
+	flags.defineCountKeys(rootCmd)
+
+	tempDir := t.TempDir()
+	sort := "max"
+
+	overwrittenSort := "min"
+	overwrittenOpts := testutil.DummyOverwrittenOptions(overwrittenSort)
+
+	var err error
+	flags.config, err = testutil.CreateTempDirAndFile(tempDir, "test_create_options_from_config_overwrite_config", testutil.DummyConfigFile(sort, overwrittenOpts))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	viper.Set("file", overwrittenOpts.File)
+	viper.Set("dump", overwrittenOpts.Dump)
+	viper.Set("load", overwrittenOpts.Load)
+	viper.Set("sort", overwrittenSort)
+	viper.Set("reverse", overwrittenOpts.Reverse)
+	viper.Set("query_string", overwrittenOpts.QueryString)
+	viper.Set("query_string_ignore_values", overwrittenOpts.QueryStringIgnoreValues)
+	viper.Set("decode_uri", overwrittenOpts.DecodeUri)
+	viper.Set("format", overwrittenOpts.Format)
+	viper.Set("noheaders", overwrittenOpts.NoHeaders)
+	viper.Set("show_footers", overwrittenOpts.ShowFooters)
+	viper.Set("limit", overwrittenOpts.Limit)
+	viper.Set("matching_groups", strings.Join(overwrittenOpts.MatchingGroups, ","))
+	viper.Set("filters", overwrittenOpts.Filters)
+	viper.Set("pos_file", overwrittenOpts.PosFile)
+	viper.Set("nosave_pos", overwrittenOpts.NoSavePos)
+	viper.Set("location", overwrittenOpts.Location)
+	viper.Set("output", overwrittenOpts.Output)
+	viper.Set("percentiles", testutil.IntSliceToString(overwrittenOpts.Percentiles))
+	viper.Set("pagination_limit", overwrittenOpts.PaginationLimit)
+
+	// json
+	viper.Set("json.uri_key", overwrittenOpts.JSON.UriKey)
+	viper.Set("json.method_key", overwrittenOpts.JSON.MethodKey)
+	viper.Set("json.time_key", overwrittenOpts.JSON.TimeKey)
+	viper.Set("json.restime_key", overwrittenOpts.JSON.ResponseTimeKey)
+	viper.Set("json.reqtime_key", overwrittenOpts.JSON.RequestTimeKey)
+	viper.Set("json.body_bytes_key", overwrittenOpts.JSON.BodyBytesKey)
+	viper.Set("json.status_key", overwrittenOpts.JSON.StatusKey)
+
+	// ltsv
+	viper.Set("ltsv.uri_label", overwrittenOpts.LTSV.UriLabel)
+	viper.Set("ltsv.method_label", overwrittenOpts.LTSV.MethodLabel)
+	viper.Set("ltsv.time_label", overwrittenOpts.LTSV.TimeLabel)
+	viper.Set("ltsv.apptime_label", overwrittenOpts.LTSV.ApptimeLabel)
+	viper.Set("ltsv.reqtime_label", overwrittenOpts.LTSV.ReqtimeLabel)
+	viper.Set("ltsv.size_label", overwrittenOpts.LTSV.SizeLabel)
+	viper.Set("ltsv.status_label", overwrittenOpts.LTSV.StatusLabel)
+
+	// regexp
+	viper.Set("regexp.pattern", overwrittenOpts.Regexp.Pattern)
+	viper.Set("regexp.uri_subexp", overwrittenOpts.Regexp.UriSubexp)
+	viper.Set("regexp.method_subexp", overwrittenOpts.Regexp.MethodSubexp)
+	viper.Set("regexp.time_subexp", overwrittenOpts.Regexp.TimeSubexp)
+	viper.Set("regexp.restime_subexp", overwrittenOpts.Regexp.ResponseTimeSubexp)
+	viper.Set("regexp.reqtime_subexp", overwrittenOpts.Regexp.RequestTimeSubexp)
+	viper.Set("regexp.body_bytes_subexp", overwrittenOpts.Regexp.BodyBytesSubexp)
+	viper.Set("regexp.status_subexp", overwrittenOpts.Regexp.StatusSubexp)
+
+	// pcap
+	viper.Set("pcap.server_ips", strings.Join(overwrittenOpts.Pcap.ServerIPs, ","))
+	viper.Set("pcap.server_port", overwrittenOpts.Pcap.ServerPort)
+
+	// count
+	viper.Set("count.keys", overwrittenOpts.Count.Keys)
+
+	var opts *options.Options
+	opts, err = flags.createOptionsFromConfig(rootCmd)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if diff := cmp.Diff(overwrittenOpts, opts); diff != "" {
+		t.Errorf("%s", diff)
+	}
+}
diff --git a/cmd/alp/cmd/json.go b/cmd/alp/cmd/json.go
index a5c462f..2e34940 100644
--- a/cmd/alp/cmd/json.go
+++ b/cmd/alp/cmd/json.go
@@ -3,23 +3,19 @@ package cmd
 import (
 	"os"
 
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/parsers"
 	"github.com/tkuchiki/alp/profiler"
 
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/tkuchiki/alp/stats"
 )
 
-func NewJSONCmd() *cobra.Command {
+func NewJSONCmd(commandFlags *flags) *cobra.Command {
 	var jsonCmd = &cobra.Command{
 		Use:   "json",
 		Short: "Profile the logs for JSON",
 		Long:  `Profile the logs for JSON`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			sortOptions := stats.NewSortOptions()
-			opts, err := createJSONOptions(cmd, sortOptions)
+			opts, err := commandFlags.createJSONOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -36,94 +32,18 @@ func NewJSONCmd() *cobra.Command {
 				opts.JSON.ResponseTimeKey, opts.JSON.RequestTimeKey, opts.JSON.BodyBytesKey, opts.JSON.StatusKey)
 			parser := parsers.NewJSONParser(f, keys, opts.QueryString, opts.QueryStringIgnoreValues)
 
-			err = prof.Run(sortOptions, parser)
+			err = prof.Run(commandFlags.sortOptions, parser)
 
 			return err
 		},
 	}
 
-	defineOptions(jsonCmd)
+	commandFlags.defineProfileOptions(jsonCmd)
+	commandFlags.defineJSONOptions(jsonCmd)
 
-	jsonCmd.PersistentFlags().StringP("uri-key", "", options.DefaultUriKeyOption, "Change the uri key")
-	jsonCmd.PersistentFlags().StringP("method-key", "", options.DefaultMethodKeyOption, "Change the method key")
-	jsonCmd.PersistentFlags().StringP("time-key", "", options.DefaultTimeKeyOption, "Change the time key")
-	jsonCmd.PersistentFlags().StringP("restime-key", "", options.DefaultResponseTimeKeyOption, "Change the response_time key")
-	jsonCmd.PersistentFlags().StringP("reqtime-key", "", options.DefaultRequestTimeKeyOption, "Change the request_time key")
-	jsonCmd.PersistentFlags().StringP("body-bytes-key", "", options.DefaultBodyBytesKeyOption, "Change the body_bytes key")
-	jsonCmd.PersistentFlags().StringP("status-key", "", options.DefaultStatusKeyOption, "Change the status key")
+	jsonCmd.Flags().SortFlags = false
+	jsonCmd.PersistentFlags().SortFlags = false
+	jsonCmd.InheritedFlags().SortFlags = false
 
 	return jsonCmd
 }
-
-func createJSONOptions(cmd *cobra.Command, sortOptions *stats.SortOptions) (*options.Options, error) {
-	config, err := cmd.PersistentFlags().GetString("config")
-	if err != nil {
-		return nil, err
-	}
-	if config != "" {
-		bindCommonFlags(cmd)
-		bindJSONFlags(cmd)
-		return createOptionsFromConfig(cmd, sortOptions, config)
-	}
-
-	opts, err := createCommonOptionsFromFlags(cmd, sortOptions)
-	if err != nil {
-		return nil, err
-	}
-
-	uriKey, err := cmd.PersistentFlags().GetString("uri-key")
-	if err != nil {
-		return nil, err
-	}
-
-	methodKey, err := cmd.PersistentFlags().GetString("method-key")
-	if err != nil {
-		return nil, err
-	}
-
-	timeKey, err := cmd.PersistentFlags().GetString("time-key")
-	if err != nil {
-		return nil, err
-	}
-
-	responseTimeKey, err := cmd.PersistentFlags().GetString("restime-key")
-	if err != nil {
-		return nil, err
-	}
-
-	requestTimeKey, err := cmd.PersistentFlags().GetString("reqtime-key")
-	if err != nil {
-		return nil, err
-	}
-
-	bodyBytesKey, err := cmd.PersistentFlags().GetString("body-bytes-key")
-	if err != nil {
-		return nil, err
-	}
-
-	statusKey, err := cmd.PersistentFlags().GetString("status-key")
-	if err != nil {
-		return nil, err
-	}
-
-	return options.SetOptions(opts,
-		options.UriKey(uriKey),
-		options.MethodKey(methodKey),
-		options.TimeKey(timeKey),
-		options.ResponseTimeKey(responseTimeKey),
-		options.RequestTimeKey(requestTimeKey),
-		options.BodyBytesKey(bodyBytesKey),
-		options.StatusKey(statusKey),
-	), nil
-}
-
-func bindJSONFlags(cmd *cobra.Command) {
-	viper.BindPFlag("json.uri_key", cmd.PersistentFlags().Lookup("uri-key"))
-	viper.BindPFlag("json.method_key", cmd.PersistentFlags().Lookup("method-key"))
-	viper.BindPFlag("json.time_key", cmd.PersistentFlags().Lookup("time-key"))
-	viper.BindPFlag("json.restime_key", cmd.PersistentFlags().Lookup("restime-key"))
-	viper.BindPFlag("json.reqtime_key", cmd.PersistentFlags().Lookup("reqtime-key"))
-	viper.BindPFlag("json.body_bytes_key", cmd.PersistentFlags().Lookup("body-bytes-key"))
-	viper.BindPFlag("json.status_key", cmd.PersistentFlags().Lookup("status-key"))
-
-}
diff --git a/cmd/alp/cmd/json_test.go b/cmd/alp/cmd/json_test.go
index 29fe726..f630f3d 100644
--- a/cmd/alp/cmd/json_test.go
+++ b/cmd/alp/cmd/json_test.go
@@ -19,7 +19,7 @@ func TestJSONCmd(t *testing.T) {
 
 	jsonLog := testutil.JsonLog(keys)
 
-	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), jsonLog)
+	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), "test_json_cmd_temp_file", jsonLog)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/cmd/alp/cmd/ltsv.go b/cmd/alp/cmd/ltsv.go
index 3648d78..d6afe32 100644
--- a/cmd/alp/cmd/ltsv.go
+++ b/cmd/alp/cmd/ltsv.go
@@ -3,23 +3,19 @@ package cmd
 import (
 	"os"
 
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/parsers"
 	"github.com/tkuchiki/alp/profiler"
 
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/tkuchiki/alp/stats"
 )
 
-func NewLTSVCmd() *cobra.Command {
+func NewLTSVCmd(commandFlags *flags) *cobra.Command {
 	var ltsvCmd = &cobra.Command{
 		Use:   "ltsv",
 		Short: "Profile the logs for LTSV",
 		Long:  `Profile the logs for LTSV`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			sortOptions := stats.NewSortOptions()
-			opts, err := createLTSVOptions(cmd, sortOptions)
+			opts, err := commandFlags.createLTSVOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -37,94 +33,18 @@ func NewLTSVCmd() *cobra.Command {
 			)
 			parser := parsers.NewLTSVParser(f, label, opts.QueryString, opts.QueryStringIgnoreValues)
 
-			err = prof.Run(sortOptions, parser)
+			err = prof.Run(commandFlags.sortOptions, parser)
 
 			return err
 		},
 	}
 
-	defineOptions(ltsvCmd)
+	commandFlags.defineProfileOptions(ltsvCmd)
+	commandFlags.defineLTSVOptions(ltsvCmd)
 
-	ltsvCmd.PersistentFlags().StringP("uri-label", "", options.DefaultUriLabelOption, "Change the uri label")
-	ltsvCmd.PersistentFlags().StringP("method-label", "", options.DefaultMethodLabelOption, "Change the method label")
-	ltsvCmd.PersistentFlags().StringP("time-label", "", options.DefaultTimeLabelOption, "Change the time label")
-	ltsvCmd.PersistentFlags().StringP("apptime-label", "", options.DefaultApptimeLabelOption, "Change the apptime label")
-	ltsvCmd.PersistentFlags().StringP("reqtime-label", "", options.DefaultReqtimeLabelOption, "Change the reqtime label")
-	ltsvCmd.PersistentFlags().StringP("size-label", "", options.DefaultSizeLabelOption, "Change the size label")
-	ltsvCmd.PersistentFlags().StringP("status-label", "", options.DefaultStatusLabelOption, "Change the status label")
+	ltsvCmd.Flags().SortFlags = false
+	ltsvCmd.PersistentFlags().SortFlags = false
+	ltsvCmd.InheritedFlags().SortFlags = false
 
 	return ltsvCmd
 }
-
-func createLTSVOptions(cmd *cobra.Command, sortOptions *stats.SortOptions) (*options.Options, error) {
-	config, err := cmd.PersistentFlags().GetString("config")
-	if err != nil {
-		return nil, err
-	}
-	if config != "" {
-		bindCommonFlags(cmd)
-		bindLTSVFlags(cmd)
-		return createOptionsFromConfig(cmd, sortOptions, config)
-	}
-
-	opts, err := createCommonOptionsFromFlags(cmd, sortOptions)
-	if err != nil {
-		return nil, err
-	}
-
-	uriLabel, err := cmd.PersistentFlags().GetString("uri-label")
-	if err != nil {
-		return nil, err
-	}
-
-	methodLabel, err := cmd.PersistentFlags().GetString("method-label")
-	if err != nil {
-		return nil, err
-	}
-
-	timeLabel, err := cmd.PersistentFlags().GetString("time-label")
-	if err != nil {
-		return nil, err
-	}
-
-	appTimeLabel, err := cmd.PersistentFlags().GetString("apptime-label")
-	if err != nil {
-		return nil, err
-	}
-
-	reqTimeLabel, err := cmd.PersistentFlags().GetString("reqtime-label")
-	if err != nil {
-		return nil, err
-	}
-
-	sizeLabel, err := cmd.PersistentFlags().GetString("size-label")
-	if err != nil {
-		return nil, err
-	}
-
-	statusLabel, err := cmd.PersistentFlags().GetString("status-label")
-	if err != nil {
-		return nil, err
-	}
-
-	return options.SetOptions(opts,
-		// ltsv
-		options.UriLabel(uriLabel),
-		options.MethodLabel(methodLabel),
-		options.TimeLabel(timeLabel),
-		options.ApptimeLabel(appTimeLabel),
-		options.ReqtimeLabel(reqTimeLabel),
-		options.SizeLabel(sizeLabel),
-		options.StatusLabel(statusLabel),
-	), nil
-}
-
-func bindLTSVFlags(cmd *cobra.Command) {
-	viper.BindPFlag("ltsv.uri_label", cmd.PersistentFlags().Lookup("uri-label"))
-	viper.BindPFlag("ltsv.method_label", cmd.PersistentFlags().Lookup("method-label"))
-	viper.BindPFlag("ltsv.time_label", cmd.PersistentFlags().Lookup("time-label"))
-	viper.BindPFlag("ltsv.apptime_label", cmd.PersistentFlags().Lookup("apptime-label"))
-	viper.BindPFlag("ltsv.reqtime_label", cmd.PersistentFlags().Lookup("reqtime-label"))
-	viper.BindPFlag("ltsv.size_label", cmd.PersistentFlags().Lookup("size-label"))
-	viper.BindPFlag("ltsv.status_label", cmd.PersistentFlags().Lookup("status-label"))
-}
diff --git a/cmd/alp/cmd/ltsv_test.go b/cmd/alp/cmd/ltsv_test.go
index 809c917..8745627 100644
--- a/cmd/alp/cmd/ltsv_test.go
+++ b/cmd/alp/cmd/ltsv_test.go
@@ -19,7 +19,7 @@ func TestLTSVCmd(t *testing.T) {
 
 	ltsvLog := testutil.LTSVLog(keys)
 
-	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), ltsvLog)
+	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), "test_ltsv_cmd_temp_file", ltsvLog)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/cmd/alp/cmd/option.go b/cmd/alp/cmd/option.go
deleted file mode 100644
index 06b33f3..0000000
--- a/cmd/alp/cmd/option.go
+++ /dev/null
@@ -1,223 +0,0 @@
-package cmd
-
-import (
-	"github.com/tkuchiki/alp/helpers"
-
-	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/tkuchiki/alp/options"
-	"github.com/tkuchiki/alp/stats"
-)
-
-func defineOptions(cmd *cobra.Command) {
-	cmd.PersistentFlags().StringP("config", "", "", "The configuration file")
-	cmd.PersistentFlags().StringP("file", "", "", "The access log file")
-	cmd.PersistentFlags().StringP("dump", "", "", "Dump profiled data as YAML")
-	cmd.PersistentFlags().StringP("load", "", "", "Load the profiled YAML data")
-	cmd.PersistentFlags().StringP("format", "", options.DefaultFormatOption, "The output format (table, markdown, tsv, csv and html)")
-	cmd.PersistentFlags().StringP("sort", "", options.DefaultSortOption, "Output the results in sorted order")
-	cmd.PersistentFlags().BoolP("reverse", "r", false, "Sort results in reverse order")
-	cmd.PersistentFlags().BoolP("noheaders", "", false, "Output no header line at all (only --format=tsv, csv)")
-	cmd.PersistentFlags().BoolP("show-footers", "", false, "Output footer line at all (only --format=table, markdown)")
-	cmd.PersistentFlags().IntP("limit", "", options.DefaultLimitOption, "The maximum number of results to display")
-	cmd.PersistentFlags().StringP("output", "o", options.DefaultOutputOption, "Specifies the results to display, separated by commas")
-	cmd.PersistentFlags().BoolP("query-string", "q", false, "Include the URI query string")
-	cmd.PersistentFlags().BoolP("qs-ignore-values", "", false, "Ignore the value of the query string. Replace all values with xxx (only use with -q)")
-	cmd.PersistentFlags().StringP("location", "", options.DefaultLocationOption, "Location name for the timezone")
-	cmd.PersistentFlags().BoolP("decode-uri", "", false, "Decode the URI")
-	cmd.PersistentFlags().StringP("matching-groups", "m", "", "Specifies Query matching groups separated by commas")
-	cmd.PersistentFlags().StringP("filters", "f", "", "Only the logs are profiled that match the conditions")
-	cmd.PersistentFlags().StringP("pos", "", "", "The position file")
-	cmd.PersistentFlags().BoolP("nosave-pos", "", false, "Do not save position file")
-	cmd.PersistentFlags().StringP("percentiles", "", "", "Specifies the percentiles separated by commas")
-	cmd.PersistentFlags().IntP("page", "", options.DefaultPaginationLimit, "Number of pages of pagination")
-
-}
-
-func createCommonOptionsFromFlags(cmd *cobra.Command, sortOptions *stats.SortOptions) (*options.Options, error) {
-	file, err := cmd.PersistentFlags().GetString("file")
-	if err != nil {
-		return nil, err
-	}
-
-	dump, err := cmd.PersistentFlags().GetString("dump")
-	if err != nil {
-		return nil, err
-	}
-
-	load, err := cmd.PersistentFlags().GetString("load")
-	if err != nil {
-		return nil, err
-	}
-
-	format, err := cmd.PersistentFlags().GetString("format")
-	if err != nil {
-		return nil, err
-	}
-
-	sort, err := cmd.PersistentFlags().GetString("sort")
-	if err != nil {
-		return nil, err
-	}
-
-	err = sortOptions.SetAndValidate(sort)
-	if err != nil {
-		return nil, err
-	}
-
-	reverse, err := cmd.PersistentFlags().GetBool("reverse")
-	if err != nil {
-		return nil, err
-	}
-
-	noHeaders, err := cmd.PersistentFlags().GetBool("noheaders")
-	if err != nil {
-		return nil, err
-	}
-
-	showFooters, err := cmd.PersistentFlags().GetBool("show-footers")
-	if err != nil {
-		return nil, err
-	}
-
-	limit, err := cmd.PersistentFlags().GetInt("limit")
-	if err != nil {
-		return nil, err
-	}
-
-	output, err := cmd.PersistentFlags().GetString("output")
-	if err != nil {
-		return nil, err
-	}
-
-	queryString, err := cmd.PersistentFlags().GetBool("query-string")
-	if err != nil {
-		return nil, err
-	}
-
-	queryStringIgnoreValues, err := cmd.PersistentFlags().GetBool("qs-ignore-values")
-	if err != nil {
-		return nil, err
-	}
-
-	decodeUri, err := cmd.PersistentFlags().GetBool("decode-uri")
-	if err != nil {
-		return nil, err
-	}
-
-	location, err := cmd.PersistentFlags().GetString("location")
-	if err != nil {
-		return nil, err
-	}
-
-	matchingGroups, err := cmd.PersistentFlags().GetString("matching-groups")
-	if err != nil {
-		return nil, err
-	}
-
-	filters, err := cmd.PersistentFlags().GetString("filters")
-	if err != nil {
-		return nil, err
-	}
-
-	pos, err := cmd.PersistentFlags().GetString("pos")
-	if err != nil {
-		return nil, err
-	}
-
-	noSavePos, err := cmd.PersistentFlags().GetBool("nosave-pos")
-	if err != nil {
-		return nil, err
-	}
-
-	ps, err := cmd.PersistentFlags().GetString("percentiles")
-	if err != nil {
-		return nil, err
-	}
-
-	var percentiles []int
-	if ps != "" {
-		percentiles, err = helpers.SplitCSVIntoInts(ps)
-		if err != nil {
-			return nil, err
-		}
-
-		if err = helpers.ValidatePercentiles(percentiles); err != nil {
-			return nil, err
-		}
-	}
-
-	paginationLimit, err := cmd.PersistentFlags().GetInt("page")
-	if err != nil {
-		return nil, err
-	}
-
-	opts := options.NewOptions()
-
-	return options.SetOptions(opts,
-		options.File(file),
-		options.Dump(dump),
-		options.Load(load),
-		options.Sort(sortOptions.SortType()),
-		options.Reverse(reverse),
-		options.Format(format),
-		options.Limit(limit),
-		options.Output(output),
-		options.QueryString(queryString),
-		options.QueryStringIgnoreValues(queryStringIgnoreValues),
-		options.DecodeUri(decodeUri),
-		options.Location(location),
-		options.NoHeaders(noHeaders),
-		options.ShowFooters(showFooters),
-		options.CSVGroups(matchingGroups),
-		options.Filters(filters),
-		options.PosFile(pos),
-		options.NoSavePos(noSavePos),
-		options.Percentiles(percentiles),
-		options.PaginationLimit(paginationLimit),
-	), nil
-}
-
-func createOptionsFromConfig(cmd *cobra.Command, sortOptions *stats.SortOptions, config string) (*options.Options, error) {
-	opts := options.NewOptions()
-	viper.SetConfigFile(config)
-	viper.SetConfigType("yaml")
-
-	if err := viper.ReadInConfig(); err != nil {
-		return nil, err
-	}
-
-	if err := viper.Unmarshal(opts); err != nil {
-		return nil, err
-	}
-
-	if err := sortOptions.SetAndValidate(opts.Sort); err != nil {
-		return nil, err
-	}
-	opts.Sort = sortOptions.SortType()
-
-	return opts, nil
-}
-
-func bindCommonFlags(cmd *cobra.Command) {
-	viper.BindPFlag("file", cmd.PersistentFlags().Lookup("file"))
-	viper.BindPFlag("dump", cmd.PersistentFlags().Lookup("dump"))
-	viper.BindPFlag("load", cmd.PersistentFlags().Lookup("load"))
-	viper.BindPFlag("sort", cmd.PersistentFlags().Lookup("sort"))
-	viper.BindPFlag("reverse", cmd.PersistentFlags().Lookup("reverse"))
-	viper.BindPFlag("query_string", cmd.PersistentFlags().Lookup("query-string"))
-	viper.BindPFlag("query_string_ignore_values", cmd.PersistentFlags().Lookup("qs-ignore-values"))
-	viper.BindPFlag("decode_uri", cmd.PersistentFlags().Lookup("decode-uri"))
-	viper.BindPFlag("format", cmd.PersistentFlags().Lookup("format"))
-	viper.BindPFlag("noheaders", cmd.PersistentFlags().Lookup("noheaders"))
-	viper.BindPFlag("show_footers", cmd.PersistentFlags().Lookup("show-footers"))
-	viper.BindPFlag("limit", cmd.PersistentFlags().Lookup("limit"))
-	viper.BindPFlag("matching_groups", cmd.PersistentFlags().Lookup("matching-groups"))
-	viper.BindPFlag("filters", cmd.PersistentFlags().Lookup("filters"))
-	viper.BindPFlag("pos_file", cmd.PersistentFlags().Lookup("pos"))
-	viper.BindPFlag("nosave_pos", cmd.PersistentFlags().Lookup("nosave-pos"))
-	viper.BindPFlag("location", cmd.PersistentFlags().Lookup("location"))
-	viper.BindPFlag("output", cmd.PersistentFlags().Lookup("output"))
-	viper.BindPFlag("percentiles", cmd.PersistentFlags().Lookup("percentiles"))
-	viper.BindPFlag("pagenation_limit", cmd.PersistentFlags().Lookup("page"))
-}
diff --git a/cmd/alp/cmd/pcap.go b/cmd/alp/cmd/pcap.go
index 49117cf..57905f7 100644
--- a/cmd/alp/cmd/pcap.go
+++ b/cmd/alp/cmd/pcap.go
@@ -3,23 +3,19 @@ package cmd
 import (
 	"os"
 
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/parsers"
 	"github.com/tkuchiki/alp/profiler"
 
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/tkuchiki/alp/stats"
 )
 
-func NewPcapCmd() *cobra.Command {
+func NewPcapCmd(commandFlags *flags) *cobra.Command {
 	var pcapCmd = &cobra.Command{
 		Use:   "pcap",
 		Short: "Profile the HTTP requests for captured packets",
 		Long:  `Profile the HTTP requests for captured packets`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			sortOptions := stats.NewSortOptions()
-			opts, err := createPcapOptions(cmd, sortOptions)
+			opts, err := commandFlags.createPcapOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -37,54 +33,18 @@ func NewPcapCmd() *cobra.Command {
 				return err
 			}
 
-			err = prof.Run(sortOptions, parser)
+			err = prof.Run(commandFlags.sortOptions, parser)
 
 			return err
 		},
 	}
 
-	defineOptions(pcapCmd)
+	commandFlags.defineProfileOptions(pcapCmd)
+	commandFlags.definePcapOptions(pcapCmd)
 
-	pcapCmd.PersistentFlags().StringSliceP("pcap-server-ip", "", []string{options.DefaultPcapServerIPsOption[0]}, "HTTP server IP address of the captured packets")
-	pcapCmd.PersistentFlags().Uint16P("pcap-server-port", "", options.DefaultPcapServerPortOption, "HTTP server TCP port of the captured packets")
+	pcapCmd.Flags().SortFlags = false
+	pcapCmd.PersistentFlags().SortFlags = false
+	pcapCmd.InheritedFlags().SortFlags = false
 
 	return pcapCmd
 }
-
-func createPcapOptions(cmd *cobra.Command, sortOptions *stats.SortOptions) (*options.Options, error) {
-	config, err := cmd.PersistentFlags().GetString("config")
-	if err != nil {
-		return nil, err
-	}
-	if config != "" {
-		bindCommonFlags(cmd)
-		bindPcapFlags(cmd)
-		return createOptionsFromConfig(cmd, sortOptions, config)
-	}
-
-	opts, err := createCommonOptionsFromFlags(cmd, sortOptions)
-	if err != nil {
-		return nil, err
-	}
-
-	serverIPs, err := cmd.PersistentFlags().GetStringSlice("pcap-server-ip")
-	if err != nil {
-		return nil, err
-	}
-
-	serverPort, err := cmd.PersistentFlags().GetUint16("pcap-server-port")
-	if err != nil {
-		return nil, err
-	}
-
-	return options.SetOptions(opts,
-		options.PcapServerIPs(serverIPs),
-		options.PcapServerPort(serverPort),
-	), nil
-}
-
-func bindPcapFlags(cmd *cobra.Command) {
-	viper.BindPFlag("pcap.server_ips", cmd.PersistentFlags().Lookup("pcap-server-ip"))
-	viper.BindPFlag("pcap.server_port", cmd.PersistentFlags().Lookup("pcap-server-port"))
-
-}
diff --git a/cmd/alp/cmd/regexp.go b/cmd/alp/cmd/regexp.go
index 4c97abf..b86e999 100644
--- a/cmd/alp/cmd/regexp.go
+++ b/cmd/alp/cmd/regexp.go
@@ -3,23 +3,19 @@ package cmd
 import (
 	"os"
 
-	"github.com/tkuchiki/alp/options"
 	"github.com/tkuchiki/alp/parsers"
 	"github.com/tkuchiki/alp/profiler"
 
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/tkuchiki/alp/stats"
 )
 
-func NewRegexpCmd() *cobra.Command {
+func NewRegexpCmd(commandFlags *flags) *cobra.Command {
 	var regexpCmd = &cobra.Command{
 		Use:   "regexp",
 		Short: "Profile the logs that match a regular expression",
 		Long:  `Profile the logs that match a regular expression`,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			sortOptions := stats.NewSortOptions()
-			opts, err := createRegexpOptions(cmd, sortOptions)
+			opts, err := commandFlags.createRegexpOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -39,101 +35,18 @@ func NewRegexpCmd() *cobra.Command {
 				return err
 			}
 
-			err = prof.Run(sortOptions, parser)
+			err = prof.Run(commandFlags.sortOptions, parser)
 
 			return err
 		},
 	}
 
-	defineOptions(regexpCmd)
+	commandFlags.defineProfileOptions(regexpCmd)
+	commandFlags.defineRegexpOptions(regexpCmd)
 
-	regexpCmd.PersistentFlags().StringP("pattern", "", options.DefaultPatternOption, "Regular expressions pattern matching the log")
-	regexpCmd.PersistentFlags().StringP("uri-subexp", "", options.DefaultUriSubexpOption, "Change the uri sub expression")
-	regexpCmd.PersistentFlags().StringP("method-subexp", "", options.DefaultMethodSubexpOption, "Change the method sub expression")
-	regexpCmd.PersistentFlags().StringP("time-subexp", "", options.DefaultTimeSubexpOption, "Change the time sub expression")
-	regexpCmd.PersistentFlags().StringP("restime-subexp", "", options.DefaultResponseTimeSubexpOption, "Change the response_time sub expression")
-	regexpCmd.PersistentFlags().StringP("reqtime-subexp", "", options.DefaultRequestTimeSubexpOption, "Change the request_time sub expression")
-	regexpCmd.PersistentFlags().StringP("body-bytes-subexp", "", options.DefaultBodyBytesSubexpOption, "Change the body_bytes sub expression")
-	regexpCmd.PersistentFlags().StringP("status-subexp", "", options.DefaultStatusSubexpOption, "Change the status sub expression")
+	regexpCmd.Flags().SortFlags = false
+	regexpCmd.PersistentFlags().SortFlags = false
+	regexpCmd.InheritedFlags().SortFlags = false
 
 	return regexpCmd
 }
-
-func createRegexpOptions(cmd *cobra.Command, sortOptions *stats.SortOptions) (*options.Options, error) {
-	config, err := cmd.PersistentFlags().GetString("config")
-	if err != nil {
-		return nil, err
-	}
-	if config != "" {
-		bindCommonFlags(cmd)
-		bindRegexpFlags(cmd)
-		return createOptionsFromConfig(cmd, sortOptions, config)
-	}
-
-	opts, err := createCommonOptionsFromFlags(cmd, sortOptions)
-	if err != nil {
-		return nil, err
-	}
-
-	pattern, err := cmd.PersistentFlags().GetString("pattern")
-	if err != nil {
-		return nil, err
-	}
-
-	uriSubexp, err := cmd.PersistentFlags().GetString("uri-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	methodSubexp, err := cmd.PersistentFlags().GetString("method-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	timeSubexp, err := cmd.PersistentFlags().GetString("time-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	restimeSubexp, err := cmd.PersistentFlags().GetString("restime-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	reqtimeSubexp, err := cmd.PersistentFlags().GetString("reqtime-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	bodyBytesSubexp, err := cmd.PersistentFlags().GetString("body-bytes-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	statusSubexp, err := cmd.PersistentFlags().GetString("status-subexp")
-	if err != nil {
-		return nil, err
-	}
-
-	return options.SetOptions(opts,
-		options.Pattern(pattern),
-		options.UriSubexp(uriSubexp),
-		options.MethodSubexp(methodSubexp),
-		options.TimeSubexp(timeSubexp),
-		options.ResponseTimeSubexp(restimeSubexp),
-		options.RequestTimeSubexp(reqtimeSubexp),
-		options.BodyBytesSubexp(bodyBytesSubexp),
-		options.StatusSubexp(statusSubexp),
-	), nil
-}
-
-func bindRegexpFlags(cmd *cobra.Command) {
-	viper.BindPFlag("regexp.pattern", cmd.PersistentFlags().Lookup("pattern"))
-	viper.BindPFlag("regexp.uri_subexp", cmd.PersistentFlags().Lookup("uri-subexp"))
-	viper.BindPFlag("regexp.method_subexp", cmd.PersistentFlags().Lookup("method-subexp"))
-	viper.BindPFlag("regexp.time_subexp", cmd.PersistentFlags().Lookup("time-subexp"))
-	viper.BindPFlag("regexp.restime_subexp", cmd.PersistentFlags().Lookup("restime-subexp"))
-	viper.BindPFlag("regexp.reqtime_subexp", cmd.PersistentFlags().Lookup("reqtime-subexp"))
-	viper.BindPFlag("regexp.body_bytes_subexp", cmd.PersistentFlags().Lookup("body-bytes-subexp"))
-	viper.BindPFlag("regexp.status_subexp", cmd.PersistentFlags().Lookup("status-subexp"))
-}
diff --git a/cmd/alp/cmd/regexp_test.go b/cmd/alp/cmd/regexp_test.go
index 199bdac..1a5b837 100644
--- a/cmd/alp/cmd/regexp_test.go
+++ b/cmd/alp/cmd/regexp_test.go
@@ -19,7 +19,7 @@ func TestRegexpCmd(t *testing.T) {
 
 	regexpLog := testutil.RegexpLog()
 
-	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), regexpLog)
+	tempFile, err := testutil.CreateTempDirAndFile(t.TempDir(), "test_regexp_cmd_temp_file", regexpLog)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/cmd/alp/cmd/root.go b/cmd/alp/cmd/root.go
index dcc619d..a2aaa0b 100644
--- a/cmd/alp/cmd/root.go
+++ b/cmd/alp/cmd/root.go
@@ -23,12 +23,16 @@ func NewRootCmd(version string) *cobra.Command {
 		},
 	}
 
-	rootCmd.AddCommand(NewLTSVCmd())
-	rootCmd.AddCommand(NewJSONCmd())
-	rootCmd.AddCommand(NewRegexpCmd())
-	rootCmd.AddCommand(NewPcapCmd())
-	rootCmd.AddCommand(NewDiffCmd())
-	rootCmd.AddCommand(NewCountCmd())
+	commandFlags := newFlags()
+
+	commandFlags.defineGlobalOptions(rootCmd)
+
+	rootCmd.AddCommand(NewLTSVCmd(commandFlags))
+	rootCmd.AddCommand(NewJSONCmd(commandFlags))
+	rootCmd.AddCommand(NewRegexpCmd(commandFlags))
+	rootCmd.AddCommand(NewPcapCmd(commandFlags))
+	rootCmd.AddCommand(NewDiffCmd(commandFlags))
+	rootCmd.AddCommand(NewCountCmd(commandFlags))
 	rootCmd.SetVersionTemplate(fmt.Sprintln(version))
 
 	return rootCmd
diff --git a/go.mod b/go.mod
index 3082bf0..dc59b57 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/tkuchiki/alp
 require (
 	github.com/Songmu/go-ltsv v0.0.0-20200903131950-a608c3f6a014
 	github.com/antonmedv/expr v1.8.9
+	github.com/google/go-cmp v0.5.9
 	github.com/google/gopacket v1.1.19
 	github.com/kylelemons/godebug v1.1.0
 	github.com/olekukonko/tablewriter v0.0.5
diff --git a/internal/testutil/cmd.go b/internal/testutil/cmd.go
index 1786cba..e4415b2 100644
--- a/internal/testutil/cmd.go
+++ b/internal/testutil/cmd.go
@@ -1,11 +1,14 @@
 package testutil
 
 import (
-	"fmt"
+	"bytes"
 	"os"
 	"path/filepath"
 	"strings"
-	"time"
+	"text/template"
+
+	"github.com/tkuchiki/alp/options"
+	"github.com/tkuchiki/alp/stats"
 )
 
 type LogKeys struct {
@@ -42,8 +45,8 @@ func NewLTSVLogKeys() LogKeys {
 	}
 }
 
-func CreateTempDirAndFile(dir, content string) (string, error) {
-	fpath := filepath.Join(dir, fmt.Sprint(time.Now().UnixNano()))
+func CreateTempDirAndFile(dir, filename, content string) (string, error) {
+	fpath := filepath.Join(dir, filename)
 	err := os.WriteFile(fpath, []byte(content), 0644)
 
 	return fpath, err
@@ -108,3 +111,213 @@ func ConfigFile() string {
 reverse: true
 query_string: true`
 }
+
+func DummyOptions(sort string) *options.Options {
+	sortOptions := stats.NewSortOptions()
+	sortOptions.SetAndValidate(sort)
+
+	return &options.Options{
+		File:                    "/path/to/file",
+		Sort:                    sortOptions.SortType(),
+		Location:                "dummy",
+		Reverse:                 false,
+		QueryString:             false,
+		QueryStringIgnoreValues: false,
+		DecodeUri:               false,
+		Format:                  "markdown",
+		Limit:                   100,
+		NoHeaders:               false,
+		ShowFooters:             false,
+		MatchingGroups: []string{
+			"/foo/.+",
+		},
+		Filters:         ".Uri == '/foo/bar'",
+		Output:          "count,uri,min,max",
+		PosFile:         "/path/to/pos",
+		NoSavePos:       false,
+		Percentiles:     []int{1, 5},
+		PaginationLimit: 10,
+		LTSV: &options.LTSVOptions{
+			UriLabel:     "u",
+			MethodLabel:  "m",
+			TimeLabel:    "t",
+			ApptimeLabel: "a",
+			ReqtimeLabel: "r",
+			SizeLabel:    "sz",
+			StatusLabel:  "st",
+		},
+		JSON: &options.JSONOptions{
+			UriKey:          "u",
+			MethodKey:       "m",
+			TimeKey:         "t",
+			ResponseTimeKey: "res",
+			RequestTimeKey:  "req",
+			BodyBytesKey:    "b",
+			StatusKey:       "s",
+		},
+		Regexp: &options.RegexpOptions{
+			Pattern:            "dummy pattern",
+			UriSubexp:          "u",
+			MethodSubexp:       "m",
+			TimeSubexp:         "t",
+			ResponseTimeSubexp: "res",
+			RequestTimeSubexp:  "req",
+			BodyBytesSubexp:    "b",
+			StatusSubexp:       "s",
+		},
+		Pcap: &options.PcapOptions{
+			ServerIPs: []string{
+				"192.168.1.10",
+			},
+			ServerPort: 12345,
+		},
+		Count: &options.CountOptions{
+			Keys: []string{
+				"ua",
+			},
+		},
+	}
+}
+
+func DummyOverwrittenOptions(sort string) *options.Options {
+	sortOptions := stats.NewSortOptions()
+	sortOptions.SetAndValidate(sort)
+
+	return &options.Options{
+		File:                    "/path/to/overwritten/file",
+		Sort:                    sortOptions.SortType(),
+		Location:                "overwritten location",
+		Reverse:                 true,
+		QueryString:             true,
+		QueryStringIgnoreValues: true,
+		DecodeUri:               true,
+		Format:                  "tsv",
+		Limit:                   200,
+		NoHeaders:               true,
+		ShowFooters:             true,
+		MatchingGroups: []string{
+			"/foo/bar/.+",
+			"/bar/.+",
+		},
+		Filters:         ".Status == 200",
+		Output:          "uri,avg",
+		PosFile:         "/path/to/overwritten/pos",
+		NoSavePos:       true,
+		Percentiles:     []int{5, 9},
+		PaginationLimit: 20,
+		LTSV: &options.LTSVOptions{
+			UriLabel:     "u2",
+			MethodLabel:  "m2",
+			TimeLabel:    "t2",
+			ApptimeLabel: "a2",
+			ReqtimeLabel: "r2",
+			SizeLabel:    "sz2",
+			StatusLabel:  "st2",
+		},
+		JSON: &options.JSONOptions{
+			UriKey:          "u2",
+			MethodKey:       "m2",
+			TimeKey:         "t2",
+			ResponseTimeKey: "res2",
+			RequestTimeKey:  "req2",
+			BodyBytesKey:    "b2",
+			StatusKey:       "s2",
+		},
+		Regexp: &options.RegexpOptions{
+			UriSubexp:          "u2",
+			MethodSubexp:       "m2",
+			TimeSubexp:         "t2",
+			ResponseTimeSubexp: "res2",
+			RequestTimeSubexp:  "req2",
+			BodyBytesSubexp:    "b2",
+			StatusSubexp:       "s2",
+		},
+		Pcap: &options.PcapOptions{
+			ServerIPs: []string{
+				"192.168.1.20",
+			},
+			ServerPort: 54321,
+		},
+		Count: &options.CountOptions{
+			Keys: []string{
+				"host",
+				"user_agent",
+			},
+		},
+	}
+}
+
+func DummyConfigFile(sort string, dummyOpts *options.Options) string {
+	configTmpl := `file: {{ .File }}
+sort: ` + sort + `
+reverse: {{ .Reverse }}
+query_string: {{ .QueryString }}
+query_string_ignore_values: {{ .QueryStringIgnoreValues }}
+decode_uri: {{ .DecodeUri }}
+format: {{ .Format }}
+limit: {{ .Limit }}
+noheaders: {{ .NoHeaders }}
+show_footers: {{ .ShowFooters }}
+matching_groups:
+{{ range .MatchingGroups }}
+  - {{ . }}
+{{ end }}
+filters: {{ .Filters }}
+output: {{ .Output }}
+pos_file: {{ .PosFile }}
+nosave_pos: {{ .NoSavePos }}
+location: {{ .Location }}
+percentiles:
+{{ range .Percentiles }}
+  - {{ . }}
+{{ end }}
+pagination_limit: {{ .PaginationLimit }}
+ltsv:
+  uri_label: {{ .LTSV.UriLabel }}
+  method_label: {{ .LTSV.MethodLabel }}
+  time_label: {{ .LTSV.TimeLabel }}
+  apptime_label: {{ .LTSV.ApptimeLabel }}
+  reqtime_label: {{ .LTSV.ReqtimeLabel }}
+  size_label: {{ .LTSV.SizeLabel }}
+  status_label: {{ .LTSV.StatusLabel }}
+json:
+  uri_key: {{ .JSON.UriKey }}
+  method_key: {{ .JSON.MethodKey }}
+  time_key: {{ .JSON.TimeKey }}
+  response_time_key: {{ .JSON.ResponseTimeKey }}
+  request_time_key: {{ .JSON.RequestTimeKey }}
+  body_bytes_key: {{ .JSON.BodyBytesKey }}
+  status_key: {{ .JSON.StatusKey }}
+regexp:
+  pattern: {{ .Regexp.Pattern }}
+  uri_subexp: {{ .Regexp.UriSubexp }}
+  method_subexp: {{ .Regexp.MethodSubexp }}
+  time_subexp: {{ .Regexp.TimeSubexp }}
+  response_time_subexp: {{ .Regexp.ResponseTimeSubexp }}
+  request_time_subexp: {{ .Regexp.RequestTimeSubexp }}
+  body_bytes_subexp: {{ .Regexp.BodyBytesSubexp }}
+  status_subexp: {{ .Regexp.StatusSubexp }}
+pcap:
+  server_ips:
+{{ range .Pcap.ServerIPs }}
+    - {{ . }}
+{{ end }}
+  server_port: {{ .Pcap.ServerPort }}
+count:
+  keys:
+{{ range .Count.Keys }}
+    - {{ . }}
+{{ end }}
+`
+	t, err := template.New("dummy_config").Parse(configTmpl)
+	if err != nil {
+		panic(err)
+	}
+
+	var buf bytes.Buffer
+	if err = t.Execute(&buf, dummyOpts); err != nil {
+		panic(err)
+	}
+
+	return buf.String()
+}
diff --git a/internal/testutil/strconv.go b/internal/testutil/strconv.go
new file mode 100644
index 0000000..df19f34
--- /dev/null
+++ b/internal/testutil/strconv.go
@@ -0,0 +1,10 @@
+package testutil
+
+import (
+	"fmt"
+	"strings"
+)
+
+func IntSliceToString(si []int) string {
+	return strings.Trim(strings.Replace(fmt.Sprint(si), " ", ",", -1), "[]")
+}
diff --git a/options/option.go b/options/option.go
index 81018cf..d44f36b 100644
--- a/options/option.go
+++ b/options/option.go
@@ -82,6 +82,7 @@ type Options struct {
 	Regexp                  *RegexpOptions `mapstructure:"regexp"`
 	JSON                    *JSONOptions   `mapstructure:"json"`
 	Pcap                    *PcapOptions   `mapstructure:"pcap"`
+	Count                   *CountOptions  `mapstructure:"count"`
 }
 
 type LTSVOptions struct {
@@ -116,8 +117,12 @@ type JSONOptions struct {
 }
 
 type PcapOptions struct {
-	ServerIPs  []string `yaml:"server_ips"`
-	ServerPort uint16   `yaml:"server_port"`
+	ServerIPs  []string `mapstructure:"server_ips"`
+	ServerPort uint16   `mapstructure:"server_port"`
+}
+
+type CountOptions struct {
+	Keys []string `mapstructure:"keys"`
 }
 
 type Option func(*Options)
@@ -487,6 +492,15 @@ func PcapServerPort(n uint16) Option {
 	}
 }
 
+// count
+func CountKeys(ss []string) Option {
+	return func(opts *Options) {
+		if len(ss) > 0 {
+			opts.Count.Keys = ss
+		}
+	}
+}
+
 func NewOptions(opt ...Option) *Options {
 	ltsv := &LTSVOptions{
 		ApptimeLabel: DefaultApptimeLabelOption,
@@ -524,6 +538,8 @@ func NewOptions(opt ...Option) *Options {
 		ServerPort: DefaultPcapServerPortOption,
 	}
 
+	count := &CountOptions{}
+
 	options := &Options{
 		Sort:            DefaultSortOption,
 		Format:          DefaultFormatOption,
@@ -536,6 +552,7 @@ func NewOptions(opt ...Option) *Options {
 		Regexp:          regexp,
 		JSON:            json,
 		Pcap:            pcap,
+		Count:           count,
 	}
 
 	for _, o := range opt {