diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go
index 0f5ac11f3..45b36bfb1 100644
--- a/cmd/frostfs-cli/modules/control/add_rule.go
+++ b/cmd/frostfs-cli/modules/control/add_rule.go
@@ -2,6 +2,7 @@ package control
 
 import (
 	"encoding/hex"
+	"errors"
 
 	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
 	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
@@ -14,6 +15,7 @@ import (
 
 const (
 	ruleFlag = "rule"
+	pathFlag = "path"
 )
 
 var addRuleCmd = &cobra.Command{
@@ -23,15 +25,13 @@ var addRuleCmd = &cobra.Command{
 	Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *"
 --rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*"
 --rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *"
+
+control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --path some_chain.json
 `,
 	Run: addRule,
 }
 
-func addRule(cmd *cobra.Command, _ []string) {
-	pk := key.Get(cmd)
-
-	target := parseTarget(cmd)
-
+func parseChain(cmd *cobra.Command) *apechain.Chain {
 	chainID, _ := cmd.Flags().GetString(chainIDFlag)
 	hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
 
@@ -43,20 +43,34 @@ func addRule(cmd *cobra.Command, _ []string) {
 		commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
 	}
 
-	rule, _ := cmd.Flags().GetStringArray(ruleFlag)
-
 	chain := new(apechain.Chain)
-	commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rule))
 	chain.ID = apechain.ID(chainIDRaw)
-	serializedChain := chain.Bytes()
+
+	if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
+		commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
+	} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
+		commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
+	} else {
+		commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
+	}
 
 	cmd.Println("Parsed chain:")
 	util.PrintHumanReadableAPEChain(cmd, chain)
 
+	return chain
+}
+
+func addRule(cmd *cobra.Command, _ []string) {
+	pk := key.Get(cmd)
+
+	target := parseTarget(cmd)
+
+	parsed := parseChain(cmd)
+
 	req := &control.AddChainLocalOverrideRequest{
 		Body: &control.AddChainLocalOverrideRequest_Body{
 			Target: target,
-			Chain:  serializedChain,
+			Chain:  parsed.Bytes(),
 		},
 	}
 
@@ -81,9 +95,12 @@ func initControlAddRuleCmd() {
 
 	ff := addRuleCmd.Flags()
 	ff.StringArray(ruleFlag, []string{}, "Rule statement")
+	ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
 	ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
 	ff.String(targetNameFlag, "", targetNameDesc)
 	ff.String(targetTypeFlag, "", targetTypeDesc)
 	_ = addRuleCmd.MarkFlagRequired(targetTypeFlag)
 	ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
+
+	addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
 }
diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go
index 6a7eca948..dfe70e7da 100644
--- a/cmd/frostfs-cli/modules/util/ape.go
+++ b/cmd/frostfs-cli/modules/util/ape.go
@@ -3,6 +3,7 @@ package util
 import (
 	"errors"
 	"fmt"
+	"os"
 	"strconv"
 	"strings"
 
@@ -57,6 +58,23 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
 	}
 }
 
+func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error {
+	data, err := os.ReadFile(path)
+	if err != nil {
+		return fmt.Errorf("read file <%s>: %w", path, err)
+	}
+
+	err = chain.UnmarshalBinary(data)
+	if err != nil {
+		err = chain.UnmarshalJSON(data)
+		if err != nil {
+			return fmt.Errorf("invalid format: %w", err)
+		}
+	}
+
+	return nil
+}
+
 // ParseAPEChain parses APE chain rules.
 func ParseAPEChain(chain *apechain.Chain, rules []string) error {
 	if len(rules) == 0 {