diff --git a/README.md b/README.md
index f9b707f..69fddf6 100644
--- a/README.md
+++ b/README.md
@@ -29,8 +29,8 @@ pytest -svv
 ## Features
 
 - [ ] retreive the hw/project releases for all students
-- [ ] open "bulk issues" to report something wrong
+- [x] open "bulk issues" to report something wrong
 - [x] collect all the public keys
 - [x] import groups (create teams)
 - [x] create repos
-- [ ] archive all repos of a course
+- [x] archive all repos of a course
diff --git a/joint_teapot/__init__.py b/joint_teapot/__init__.py
index 36bdcfa..be3c3d3 100644
--- a/joint_teapot/__init__.py
+++ b/joint_teapot/__init__.py
@@ -1,3 +1,4 @@
 from joint_teapot.canvas import Canvas as Canvas
 from joint_teapot.git import Git as Git
 from joint_teapot.gitea import Gitea as Gitea
+from joint_teapot.teapot import Teapot as Teapot
diff --git a/joint_teapot/__main__.py b/joint_teapot/__main__.py
index a51d462..6c8e6b9 100644
--- a/joint_teapot/__main__.py
+++ b/joint_teapot/__main__.py
@@ -1,13 +1 @@
-from joint_teapot import Canvas, Gitea
-
 __version__ = "0.0.0"
-
-
-class Teapot:
-    def __init__(self) -> None:
-        self.canvas = Canvas()
-        self.gitea = Gitea()
-
-
-if __name__ == "__main__":
-    teapot = Teapot()
diff --git a/joint_teapot/config.py b/joint_teapot/config.py
index 868ac3e..6a97143 100644
--- a/joint_teapot/config.py
+++ b/joint_teapot/config.py
@@ -22,6 +22,9 @@ class Settings(BaseSettings):
     gitea_access_token: str = ""
     org_name: str = ""
 
+    # git
+    repos_dir: str = ""
+
     class Config:
         env_file = ".env"
         env_file_encoding = "utf-8"
diff --git a/joint_teapot/git.py b/joint_teapot/git.py
index d747e89..ee03ecc 100644
--- a/joint_teapot/git.py
+++ b/joint_teapot/git.py
@@ -6,24 +6,30 @@ from joint_teapot.config import settings
 
 
 class Git:
-    def __init__(self, org_name: str = settings.org_name, repos_dir: str = ""):
+    def __init__(
+        self, org_name: str = settings.org_name, repos_dir: str = settings.repos_dir
+    ):
         self.org_name = org_name
         if not os.path.isdir(repos_dir):
             raise Exception(f"{repos_dir} does not exist! Create it first.")
         self.repos_dir = repos_dir
 
-    def __get_repo(self, repo_name: str) -> git.Repo:
+    def clone_repo(self, repo_name: str) -> git.Repo:
         repo_dir = os.path.join(self.repos_dir, repo_name)
-        if os.path.exists(repo_dir):
-            return git.Repo(repo_dir)
         return git.Repo.clone_from(
             f"https://focs.ji.sjtu.edu.cn/git/{self.org_name}/{repo_name}",
             repo_dir,
             branch="master",
         )
 
+    def get_repo(self, repo_name: str) -> git.Repo:
+        repo_dir = os.path.join(self.repos_dir, repo_name)
+        if os.path.exists(repo_dir):
+            return git.Repo(repo_dir)
+        return self.clone_repo(repo_dir)
+
     def repo_clean_and_checkout(self, repo_name: str, checkout_dest: str) -> str:
-        repo = self.__get_repo(repo_name)
+        repo = self.get_repo(repo_name)
         repo.git.fetch("--tags", "--all", "-f")
         repo.git.reset("--hard", f"origin/master")
         repo.git.clean("-d", "-f", "-x")
diff --git a/joint_teapot/gitea.py b/joint_teapot/gitea.py
index cf00a9c..7028ca1 100644
--- a/joint_teapot/gitea.py
+++ b/joint_teapot/gitea.py
@@ -140,7 +140,7 @@ class Gitea:
                 },
             )
             self.organization_api.org_add_team_repository(
-                team["id"], self.org_name, repo["name"]
+                team["id"], self.org_name, repo_name
             )
             membership: GroupMembership
             for membership in group.get_memberships():
@@ -149,12 +149,14 @@ class Gitea:
                     raise Exception(
                         f"student with user_id {membership.user_id} not found"
                     )
-                self.organization_api.org_add_team_member(
-                    team["id"], self.__get_username_by_canvas_student(student)
+                username = self.__get_username_by_canvas_student(student)
+                self.organization_api.org_add_team_member(team["id"])
+                self.repository_api.repo_add_collaborator(
+                    self.org_name, repo_name, username
                 )
         return repo_names
 
-    def get_public_key_of_students(
+    def get_public_key_of_canvas_students(
         self, students: PaginatedList
     ) -> List[List[Dict[str, Any]]]:
         return [
@@ -162,6 +164,38 @@ class Gitea:
             for student in students
         ]
 
+    def get_repos_releases(self, repo_names: List[str]) -> List[List[Dict[str, Any]]]:
+        return [
+            self.repository_api.repo_list_releases(self.org_name, repo_name)
+            for repo_name in repo_names
+        ]
+
+    def get_all_repo_names(self) -> List[str]:
+        return [
+            data["name"] for data in self.organization_api.org_list_repos(self.org_name)
+        ]
+
+    def create_issue(
+        self,
+        repo_name: str,
+        title: str,
+        body: str,
+        assign_every_collaborators: bool = True,
+    ) -> None:
+        assignees = []
+        if assign_every_collaborators:
+            assignees = [
+                item["username"]
+                for item in self.repository_api.repo_list_collaborators(
+                    self.org_name, repo_name
+                )
+            ]
+        self.issue_api.issue_create_issue(
+            self.org_name,
+            repo_name,
+            body={"title": title, "body": body, "assignees": assignees},
+        )
+
 
 if __name__ == "__main__":
     gitea = Gitea()
diff --git a/joint_teapot/teapot.py b/joint_teapot/teapot.py
new file mode 100644
index 0000000..4a772a7
--- /dev/null
+++ b/joint_teapot/teapot.py
@@ -0,0 +1,39 @@
+from typing import Any, Dict, List
+
+from joint_teapot import Canvas, Git, Gitea
+
+
+class Teapot:
+    def __init__(self) -> None:
+        self.canvas = Canvas()
+        self.gitea = Gitea()
+        self.git = Git()
+
+    def create_personal_repos_for_all_canvas_students(self) -> List[str]:
+        return self.gitea.create_personal_repos_for_canvas_students(
+            self.canvas.students
+        )
+
+    def create_teams_and_repos_by_canvas_groups(self) -> List[str]:
+        return self.gitea.create_teams_and_repos_by_canvas_groups(
+            self.canvas.students, self.canvas.groups
+        )
+
+    def get_public_key_of_all_canvas_students(self) -> List[List[Dict[str, Any]]]:
+        return self.gitea.get_public_key_of_canvas_students(self.canvas.students)
+
+    def archieve_all_repos(self) -> List[str]:
+        return [
+            self.git.repo_clean_and_checkout(repo_name, "master")
+            for repo_name in self.gitea.get_all_repo_names()
+        ]
+
+    def create_issue_for_repos(
+        self, repo_names: List[str], title: str, body: str
+    ) -> None:
+        for repo_name in repo_names:
+            self.gitea.create_issue(repo_name, title, body)
+
+
+if __name__ == "__main__":
+    teapot = Teapot()