diff --git a/cmd/joj3/conf.go b/cmd/joj3/conf.go
index 769b324..414ea83 100644
--- a/cmd/joj3/conf.go
+++ b/cmd/joj3/conf.go
@@ -1,7 +1,11 @@
 package main
 
 import (
+	"errors"
+	"fmt"
 	"log/slog"
+	"os"
+	"regexp"
 
 	"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
 	"github.com/go-git/go-git/v5"
@@ -60,6 +64,46 @@ type OptionalCmd struct {
 	AddressSpaceLimit *bool
 }
 
+// TODO: add other fields to match? not only limit to latest commit message
+type MetaConf struct {
+	Patterns []struct {
+		Filename string
+		Regex    string
+	}
+}
+
+func parseMetaConfFile(path string) (metaConf MetaConf, err error) {
+	// FIXME: remove this default meta config, it is only for demonstration
+	if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
+		return MetaConf{
+			Patterns: []struct {
+				Filename string
+				Regex    string
+			}{
+				{
+					Filename: "conf.json",
+					Regex:    ".*",
+				},
+			},
+		}, nil
+	}
+	d := &multiconfig.DefaultLoader{}
+	d.Loader = multiconfig.MultiLoader(
+		&multiconfig.TagLoader{},
+		&multiconfig.JSONLoader{Path: path},
+	)
+	d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{})
+	if err = d.Load(&metaConf); err != nil {
+		slog.Error("parse meta conf", "error", err)
+		return
+	}
+	if err = d.Validate(&metaConf); err != nil {
+		slog.Error("validate meta conf", "error", err)
+		return
+	}
+	return
+}
+
 func parseConfFile(path string) (conf Conf, err error) {
 	d := &multiconfig.DefaultLoader{}
 	d.Loader = multiconfig.MultiLoader(
@@ -79,6 +123,10 @@ func parseConfFile(path string) (conf Conf, err error) {
 }
 
 func commitMsgToConf() (conf Conf, err error) {
+	metaConf, err := parseMetaConfFile("meta-conf.json")
+	if err != nil {
+		return
+	}
 	r, err := git.PlainOpen(".")
 	if err != nil {
 		return
@@ -93,7 +141,12 @@ func commitMsgToConf() (conf Conf, err error) {
 	}
 	msg := commit.Message
 	slog.Debug("commit msg to conf", "msg", msg)
-	// TODO: parse msg to conf name
-	conf, err = parseConfFile("conf.json")
+	for _, pattern := range metaConf.Patterns {
+		if matched, _ := regexp.MatchString(pattern.Regex, msg); matched {
+			slog.Debug("pattern matched", "pattern", pattern)
+			return parseConfFile(pattern.Filename)
+		}
+	}
+	err = fmt.Errorf("no pattern matched")
 	return
 }