diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..76fcadb
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "1.82"
diff --git a/src/cli.rs b/src/cli.rs
index 4b32007..8ede0d8 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -9,7 +9,7 @@ use anyhow::{bail, Result};
 #[command(author, version, about)]
 /// A tool for cloning all available repositories in a GitLab instance
 struct Cli {
-    /// The GitLab instance URL for fetch repositories (example: https://gitlab.local/)
+    /// The GitLab instance URL for fetch repositories (example: <https://gitlab.local>)
     #[arg(
         long,
         value_parser,
@@ -27,7 +27,7 @@ struct Cli {
     )]
     ft: String,
 
-    /// The GitLab instance URL for backup repositories (example: https://backup-gitlab.local/)
+    /// The GitLab instance URL for backup repositories (example: <https://backup-gitlab.local>)
     #[arg(
         long,
         value_parser,
@@ -123,19 +123,19 @@ struct Cli {
     #[arg(long, env = "GTLBSTR_UPLOAD_SSH")]
     upload_ssh: bool,
 
-    /// Force download repositories by insecure protocol. Does not work with the download_ssh flag
+    /// Force download repositories by insecure protocol. Does not work with the `download_ssh` flag
     #[arg(long, env = "GTLBSTR_DOWNLOAD_FORCE_HTTP")]
     download_force_http: bool,
 
-    /// Force download repositories by secure protocol. Does not work with the download_ssh flag
+    /// Force download repositories by secure protocol. Does not work with the `download_ssh` flag
     #[arg(long, env = "GTLBSTR_DOWNLOAD_FORCE_HTTPS")]
     download_force_https: bool,
 
-    /// Force upload repositories by insecure protocol. Does not work with the upload_ssh flag
+    /// Force upload repositories by insecure protocol. Does not work with the `upload_ssh` flag
     #[arg(long, env = "GTLBSTR_UPLOAD_FORCE_HTTP")]
     upload_force_http: bool,
 
-    /// Force upload repositories by secure protocol. Does not work with the upload_ssh flag
+    /// Force upload repositories by secure protocol. Does not work with the `upload_ssh` flag
     #[arg(long, env = "GTLBSTR_UPLOAD_FORCE_HTTPS")]
     upload_force_https: bool,
 
@@ -172,7 +172,7 @@ pub fn run() -> Result<()> {
     };
     tracing_subscriber::fmt().with_max_level(log_level).init();
 
-    let fetch_gl = FetchGitlabOptions::new(cli.fu, cli.ft)?;
+    let fetch_gl = FetchGitlabOptions::new(&cli.fu, &cli.ft)?;
 
     let patterns = if cli.exclude.is_some() && cli.include.is_some() {
         bail!("You cannot use the --include and --exclude flag together");
@@ -184,11 +184,7 @@ pub fn run() -> Result<()> {
 
     let upl_err = "For upload to another gitlab, you must specify both the --bt and --bu flags";
     let backup_gl = if let (Some(url), Some(token)) = (&cli.bu, &cli.bt) {
-        Some(BackupGitlabOptions::new(
-            url.clone(),
-            token.clone(),
-            cli.bg.clone(),
-        )?)
+        Some(BackupGitlabOptions::new(url, token, cli.bg.clone())?)
     } else {
         if cli.bu.is_some() || cli.bt.is_some() {
             bail!(upl_err);
diff --git a/src/cloner.rs b/src/cloner.rs
index f6a4c5a..7b8eb46 100644
--- a/src/cloner.rs
+++ b/src/cloner.rs
@@ -19,9 +19,12 @@ pub struct FetchGitlabOptions {
 }
 
 impl FetchGitlabOptions {
-    pub fn new(url: String, token: String) -> Result<Self> {
-        let url = Url::parse(&url)?;
-        Ok(Self { url, token })
+    pub fn new(url: &str, token: &str) -> Result<Self> {
+        let url = Url::parse(url)?;
+        Ok(Self {
+            url,
+            token: token.to_string(),
+        })
     }
 }
 
@@ -33,9 +36,13 @@ pub struct BackupGitlabOptions {
 }
 
 impl BackupGitlabOptions {
-    pub fn new(url: String, token: String, group: Option<String>) -> Result<Self> {
-        let url = Url::parse(&url)?;
-        Ok(Self { url, token, group })
+    pub fn new(url: &str, token: &str, group: Option<String>) -> Result<Self> {
+        let url = Url::parse(url)?;
+        Ok(Self {
+            url,
+            token: token.to_string(),
+            group,
+        })
     }
 }
 
@@ -99,9 +106,7 @@ fn make_git_path(
 ) -> String {
     if let Some(auth) = git_http_auth {
         let parts: Vec<&str> = project.http_url_to_repo.split("://").collect();
-        if parts.len() != 2 {
-            panic!("project with incorrect http path")
-        }
+        assert!(parts.len() == 2, "project with incorrect http path");
         let protocol = match force_protocol {
             ForceProtocol::No => parts[0],
             ForceProtocol::Http => "http",
@@ -165,7 +170,7 @@ async fn clone_project(
     let mut project_groups: Vec<types::Group> = Vec::new();
 
     for group in &path[..path.len() - 1] {
-        last_group = last_group + &group;
+        last_group += group;
         let g_info = {
             let mut groups_info = groups_info.lock().await;
 
@@ -186,7 +191,7 @@ async fn clone_project(
         .await?;
 
     let remote = make_git_path(&backup_project, backup_git_http_auth, backup_force_protocol);
-    git::push_backup(format!("{}/{}", dst, p_path), remote).await?;
+    git::push_backup(format!("{dst}/{p_path}"), remote).await?;
     Ok(())
 }
 
@@ -240,7 +245,7 @@ pub async fn clone(p: CloneParams) -> Result<()> {
     }
 
     if let Some(patterns) = p.patterns {
-        projects = filter_projects(projects, patterns, p.limit)?
+        projects = filter_projects(projects, patterns, p.limit)?;
     }
 
     if projects.is_empty() {
@@ -254,7 +259,7 @@ pub async fn clone(p: CloneParams) -> Result<()> {
     };
 
     if p.clear_dst {
-        clear_dst(&dst)
+        clear_dst(&dst);
     }
 
     let backup_data = if let Some(backup) = p.backup {
@@ -298,7 +303,7 @@ pub async fn clone(p: CloneParams) -> Result<()> {
                 println!(
                     "Backup group:   {} (id: {}, path: {})",
                     g.name, g.id, g.full_path
-                )
+                );
             };
         }
         println!("Local out dir: {}", &dst);
diff --git a/src/git.rs b/src/git.rs
index c59fecd..daac049 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -57,7 +57,7 @@ async fn update(path: &String, only_master: bool) -> Result<()> {
     let branches_out = git(vec!["-C", path, "branch", "-la"]).await?;
     let branches = branches_out
         .split('\n')
-        .map(|v| v.trim())
+        .map(str::trim)
         .filter(|v| !v.is_empty())
         .filter(|v| !v.starts_with("remotes/origin/HEAD"))
         .filter(|v| !v.starts_with("remotes/backup"));
@@ -104,17 +104,17 @@ async fn add_remote_backup(path: &String, remote: String) -> Result<()> {
 
 async fn push_all_remote_backup(path: String) -> Result<()> {
     if let Err(e) = git(vec!["-C", &path, "push", "-u", "backup", "--all"]).await {
-        error!("{}", e)
+        error!("{}", e);
     };
     if let Err(e) = git(vec!["-C", &path, "push", "-u", "backup", "--tags"]).await {
-        error!("{}", e)
+        error!("{}", e);
     };
     Ok(())
 }
 
 pub async fn fetch(src: String, dst: String, only_master: bool) -> Result<()> {
     match check_status(&dst).await {
-        Ok(_) => (),
+        Ok(()) => (),
         Err(_) => clone(&src, &dst).await?,
     };
     update(&dst, only_master).await
diff --git a/src/gitlab/client.rs b/src/gitlab/client.rs
index 097120c..112ed15 100644
--- a/src/gitlab/client.rs
+++ b/src/gitlab/client.rs
@@ -31,10 +31,10 @@ impl Client {
             http = http.timeout(Duration::from_secs(timeout.into()));
         }
         let http = http.build()?;
-        let limit = if let Some(opp) = opp { opp } else { 100 };
+        let limit = opp.unwrap_or(100);
         let token = token.to_string();
 
-        url.set_path(&format!("api/{}", API_VERSION));
+        url.set_path(&format!("api/{API_VERSION}"));
 
         Ok(Client {
             url,
@@ -68,7 +68,7 @@ impl Client {
             .header("PRIVATE-TOKEN", &self.token);
 
         if let Some(json) = json {
-            req = req.json(&json)
+            req = req.json(&json);
         }
 
         req
@@ -89,13 +89,13 @@ impl Client {
 
     pub async fn get_project(&self, path: String) -> reqwest::Result<types::Project> {
         let path = urlencoding::encode(&path);
-        self.request(Method::GET, format!("projects/{}", path), None, None::<()>)
+        self.request(Method::GET, format!("projects/{path}"), None, None::<()>)
             .await?
             .json::<types::Project>()
             .await
     }
 
-    fn exist<T>(&self, resp: reqwest::Result<T>) -> reqwest::Result<Option<T>> {
+    fn check_exists<T>(resp: reqwest::Result<T>) -> reqwest::Result<Option<T>> {
         match resp {
             Ok(p) => Ok(Some(p)),
             Err(e) => {
@@ -110,7 +110,7 @@ impl Client {
     }
 
     pub async fn project_exist(&self, path: String) -> reqwest::Result<Option<types::Project>> {
-        self.exist(self.get_project(path).await)
+        Client::check_exists(self.get_project(path).await)
     }
 
     /// Parse value of Link header
@@ -130,9 +130,7 @@ impl Client {
             .split(';')
             .nth(next_page_link_position)
             .expect(&invalid_link_msg);
-        if link.len() < 13 {
-            panic!("{}", invalid_link_msg);
-        }
+        assert!(link.len() >= 13, "{}", invalid_link_msg);
         link[1..link.len() - 1].to_string()
     }
 
@@ -147,7 +145,7 @@ impl Client {
 
         let method = match group {
             None => "projects".to_owned(),
-            Some(group) => format!("groups/{}/projects", group),
+            Some(group) => format!("groups/{group}/projects"),
         };
 
         let mut next_page_link_position = 0;
@@ -167,13 +165,13 @@ impl Client {
             } else {
                 let mut query = format!("order_by=id&sort=asc&per_page={}", &self.limit);
                 if only_owned {
-                    query += "&owned=true"
+                    query += "&owned=true";
                 }
                 if only_membership {
-                    query += "&only_membership=true"
+                    query += "&only_membership=true";
                 }
                 if method != "projects" {
-                    query += "&include_subgroups=true"
+                    query += "&include_subgroups=true";
                 }
                 query
             };
@@ -186,17 +184,13 @@ impl Client {
 
             projects.append(&mut resp.json::<Vec<types::Project>>().await?);
 
-            match headers.get("x-next-page") {
-                None => break,
-                Some(has_next_page) => {
-                    if has_next_page
-                        .to_str()
-                        .expect("Invalid x-next-page header")
-                        .is_empty()
-                    {
-                        break;
-                    }
-                }
+            let has_next_page = match headers.get("x-next-page") {
+                Some(h) => !h.to_str().expect("Invalid x-next-page header").is_empty(),
+                None => false,
+            };
+
+            if !has_next_page {
+                break;
             }
 
             let Some(link_header) = headers.get("link") else {
@@ -285,14 +279,14 @@ impl Client {
 
     pub async fn get_group(&self, path: &str) -> reqwest::Result<types::Group> {
         let path = urlencoding::encode(path);
-        self.request(Method::GET, format!("groups/{}", path), None, None::<()>)
+        self.request(Method::GET, format!("groups/{path}"), None, None::<()>)
             .await?
             .json::<types::Group>()
             .await
     }
 
     pub async fn group_exist(&self, path: &str) -> reqwest::Result<Option<types::Group>> {
-        self.exist(self.get_group(path).await)
+        Client::check_exists(self.get_group(path).await)
     }
 
     pub async fn make_subgroup(
@@ -351,7 +345,7 @@ impl Client {
         }
 
         match self
-            .project_exist(format!("{}/{}", current_namespace, project_slug))
+            .project_exist(format!("{current_namespace}/{project_slug}"))
             .await?
         {
             Some(p) => self.update_project(&p, project_info).await,
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
index 185d8a6..0a5689f 100644
--- a/tests/integration_test.rs
+++ b/tests/integration_test.rs
@@ -13,24 +13,25 @@ mod tests {
     const GITLAB_HOST: &str = "https://gitlab.com/";
 
     fn check_local(updated_data: Option<&String>) {
-        println!("-- check local dir");
         fn check_file_data(path: String, data: &str) {
             let mut file = File::open(path).unwrap();
             let mut content = String::new();
             file.read_to_string(&mut content).unwrap();
 
             let content = content.trim();
-            println!("-- content: {}, expected: {}", content, data);
+            println!("-- content: {content}, expected: {data}");
             assert!(content.trim() == data);
         }
 
-        let prefix = format!("{}/gitlobster_test/example", OUT_DIR);
-        let p1_path = format!("{}/project_1", prefix);
-        let p1_file_path = format!("{}/project_1", p1_path);
+        println!("-- check local dir");
+
+        let prefix = format!("{OUT_DIR}/gitlobster_test/example");
+        let p1_path = format!("{prefix}/project_1");
+        let p1_file_path = format!("{p1_path}/project_1");
         let files = vec![
             (p1_file_path.clone(), "branch1"),
-            (format!("{}/project_2/project_2", prefix), "main"),
-            (format!("{}/subgroup_1/project_3/project_3", prefix), "main"),
+            (format!("{prefix}/project_2/project_2"), "main"),
+            (format!("{prefix}/subgroup_1/project_3/project_3"), "main"),
         ];
 
         // check files in default branches
@@ -39,32 +40,32 @@ mod tests {
         }
 
         // check the second branch in project_1
-        let git_cmd = format!("git -C {} checkout branch2", p1_path);
+        let git_cmd = format!("git -C {p1_path} checkout branch2");
         Exec::shell(git_cmd).join().unwrap();
         check_file_data(p1_file_path, "branch2");
 
         // check updated file if need
         if let Some(data) = updated_data {
-            check_file_data(format!("{}/updating", p1_path), data.as_str());
+            check_file_data(format!("{p1_path}/updating"), data.as_str());
         };
-        let git_cmd = format!("git -C {} checkout branch1", p1_path);
+        let git_cmd = format!("git -C {p1_path} checkout branch1");
         Exec::shell(git_cmd).join().unwrap();
     }
 
     fn check_backup(start_time: DateTime<Utc>, gitlab_token: &str, updated_data: Option<&String>) {
-        println!("-- check backup");
-
         #[derive(Deserialize)]
         struct Project {
             description: String,
             name: String,
         }
 
-        let url_prefix = format!("{}api/v4/projects", GITLAB_HOST);
+        println!("-- check backup");
+
+        let url_prefix = format!("{GITLAB_HOST}api/v4/projects");
         let project_path = "gitlobster_test%2Fupload4%2Fgitlobster_test%2Fexample";
-        let p1_name = format!("{}%2Fproject_1", project_path);
-        let p2_name = format!("{}%2Fproject_2", project_path);
-        let p3_name = format!("{}%2Fsubgroup_1%2Fproject_3", project_path);
+        let p1_name = format!("{project_path}%2Fproject_1");
+        let p2_name = format!("{project_path}%2Fproject_2");
+        let p3_name = format!("{project_path}%2Fsubgroup_1%2Fproject_3");
         let mut files = vec![
             (&p1_name, "branch1", "project_1", "branch1"),
             (&p1_name, "branch2", "project_1", "branch2"),
@@ -80,13 +81,12 @@ mod tests {
         let client = rqw::Client::new();
         for (project, branch, file, data) in files {
             let url = format!(
-                "{}/{}/repository/files/{}/raw?ref={}&access_token={}",
-                url_prefix, project, file, branch, gitlab_token
+                "{url_prefix}/{project}/repository/files/{file}/raw?ref={branch}&access_token={gitlab_token}"
             );
             let resp = client.get(url).send().unwrap().error_for_status().unwrap();
             let content = resp.text().unwrap();
             let content = content.trim();
-            println!("-- content: {}, expected: {}", content, data);
+            println!("-- content: {content}, expected: {data}");
             assert!(content == data);
         }
 
@@ -97,7 +97,7 @@ mod tests {
             (p3_name, "project_3"),
         ];
         for (project, project_name) in projects {
-            let url = format!("{}/{}?access_token={}", url_prefix, project, gitlab_token);
+            let url = format!("{url_prefix}/{project}?access_token={gitlab_token}");
             let resp = client.get(url).send().unwrap().error_for_status().unwrap();
             let p = resp.json::<Project>().unwrap();
             let d_time_str = p.description.split(" 🦞 Synced: ").last().unwrap();
@@ -112,8 +112,7 @@ mod tests {
 
         let _ = fs::remove_dir_all(OUT_DIR);
         let url = format!(
-            "{}api/v4/groups/gitlobster_test%2Fupload4%2Fgitlobster_test?access_token={}",
-            GITLAB_HOST, gitlab_token
+            "{GITLAB_HOST}api/v4/groups/gitlobster_test%2Fupload4%2Fgitlobster_test?access_token={gitlab_token}"
         );
         let _ = rqw::Client::new().delete(url).send();
     }
@@ -121,20 +120,19 @@ mod tests {
     fn run_gitlobster(gitlab_token: &str, enable_ssh: bool) -> ExitStatus {
         let mut cmd = format!(
             "cargo run -- \
-            --ft={} \
-            --fu={} \
-            --bt={} \
-            --bu={} \
+            --ft={gitlab_token} \
+            --fu={GITLAB_HOST} \
+            --bt={gitlab_token} \
+            --bu={GITLAB_HOST} \
             --bg=gitlobster_test/upload4 \
             --only-owned \
             --include='^gitlobster_test/example' \
             --concurrency-limit=1 \
-            -d {} \
+            -d {OUT_DIR} \
             -vv",
-            gitlab_token, GITLAB_HOST, gitlab_token, GITLAB_HOST, OUT_DIR,
         );
         if enable_ssh {
-            cmd = format!("{} --download-ssh --upload-ssh", cmd)
+            cmd += " --download-ssh --upload-ssh";
         }
         Exec::shell(cmd).join().unwrap()
     }
@@ -143,8 +141,7 @@ mod tests {
         let project = "gitlobster_test%2Fexample%2Fproject_1";
         let file = "updating";
         let url = format!(
-            "{}api/v4/projects/{}/repository/files/{}?access_token={}",
-            GITLAB_HOST, project, file, gitlab_token
+            "{GITLAB_HOST}api/v4/projects/{project}/repository/files/{file}?access_token={gitlab_token}"
         );
         let id = Uuid::new_v4().to_string();
         let data = format!(
@@ -152,10 +149,9 @@ mod tests {
                 "branch": "branch2",
                 "author_email": "gitlobster@lowit.ru",
                 "author_name": "Mr. Gitlobster",
-                "content": "{}",
+                "content": "{id}",
                 "commit_message": "update"
-            }}"#,
-            id
+            }}"#
         );
         rqw::Client::new()
             .put(url)