diff --git a/README.md b/README.md
index 58a3c11e457de8c8b5d0db8287b15ebbb912834f..a6496d81151c285b28e079519a396514a48ee925 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ gitrepoman github pop-os clone
 gitrepoman github pop-os pull
 gitrepoman github pop-os checkout
 
-gitrepoman gitlab gitlab.redox-os.org clone
-gitrepoman gitlab gitlab.redox-os.org pull
-gitrepoman gitlab gitlab.redox-os.org checkout
+gitrepoman gitlab gitlab.redox-os.org redox-os clone
+gitrepoman gitlab gitlab.redox-os.org redox-os pull
+gitrepoman gitlab gitlab.redox-os.org redox-os checkout
 ```
diff --git a/src/actions.rs b/src/actions.rs
index b49ff5a9447a50eb7a3c94248ed567fdf239415e..9343b842e0670956fcf12b18c20dc51cfa1285fd 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -1,6 +1,6 @@
 use std::io;
 use std::path::Path;
-use std::process::Command;
+use std::process::{Command, Stdio};
 use rayon::prelude::*;
 
 #[derive(Debug, Deserialize, Eq, Hash)]
@@ -8,6 +8,7 @@ pub struct Repo {
     pub name: String,
     pub html_url: String,
     pub ssh_url: String,
+    pub namespace: String,
 }
 
 impl Repo {
@@ -35,7 +36,7 @@ pub enum GitError {
 }
 
 fn git_cmd(args: &[&str], name: &str) -> Result<String, (String, GitError)> {
-    match Command::new("git").args(args).status() {
+    match Command::new("git").args(args).stdout(Stdio::null()).stderr(Stdio::null()).status() {
         Ok(status) => if status.success() {
             Ok(name.to_owned())
         } else {
@@ -48,16 +49,20 @@ fn git_cmd(args: &[&str], name: &str) -> Result<String, (String, GitError)> {
 pub trait GitAction {
     fn get_repos(&self) -> Vec<Repo>;
 
-    fn list(&self) {
+    fn list(&self, namespace: &str) {
         for repo in self.get_repos() {
+            if repo.namespace == namespace {
+                continue
+            }
             println!("{}: {}", repo.name, repo.ssh_url);
         }
     }
 
-    fn clone(&self, flags: u8) {
+    fn clone(&self, flags: u8, namespace: &str) {
         let results = self.get_repos()
             .par_iter()
-            .inspect(|repo| println!("cloning {}", repo.name))
+            .filter(|repo| namespace == "" || repo.name == namespace)
+            .inspect(|repo| println!("cloning {} from {}", repo.name, repo.get_url()))
             .map(|repo| if !Path::new(&repo.name).exists() {
                 let url = if flags & 0b01 != 0 { repo.get_ssh_url() } else { repo.get_url() };
                 git_cmd(&["clone", "--recursive", url, &repo.name], &repo.name)
@@ -74,10 +79,11 @@ pub trait GitAction {
         }
     }
 
-    fn pull(&self, flags: u8) {
+    fn pull(&self, flags: u8, namespace: &str) {
         let results = self.get_repos()
             .par_iter()
-            .inspect(|repo| println!("pulling {}", repo.name))
+            .filter(|repo| namespace == "" || repo.name == namespace)
+            .inspect(|repo| println!("pulling {} from {}", repo.name, repo.get_url()))
             .map(|repo| if !Path::new(&repo.name).exists() {
                 let url = if flags & 0b01 != 0 { repo.get_ssh_url() } else { repo.get_url() };
                 git_cmd(&["clone", "--recursive", url, &repo.name], &repo.name)
@@ -96,10 +102,11 @@ pub trait GitAction {
         }
     }
 
-    fn checkout(&self, flags: u8) {
+    fn checkout(&self, flags: u8, namespace: &str) {
         let results = self.get_repos()
             .par_iter()
-            .inspect(|repo| println!("checking out {}", repo.name))
+            .filter(|repo| namespace == "" || repo.name == namespace)
+            .inspect(|repo| println!("checking out {} from {}", repo.name, repo.get_url()))
             .map(|repo| if !Path::new(&repo.name).exists() {
                 let url = if flags & 0b01 != 0 { repo.get_ssh_url() } else { repo.get_url() };
                 git_cmd(&["clone", "--recursive", url, &repo.name], &repo.name)
diff --git a/src/github_impl.rs b/src/github_impl.rs
index a00c3e44a78a8dca73956c412ad74d7f7bf71158..3e8dcbb3504d7bab66dfcd3e7ae7223112e2aa3f 100644
--- a/src/github_impl.rs
+++ b/src/github_impl.rs
@@ -15,18 +15,30 @@ impl GitHub {
     }
 }
 
+#[derive(Debug, Deserialize)]
+pub struct GithubRepo {
+    pub name: String,
+    pub html_url: String,
+    pub ssh_url: String,
+}
+
 impl GitAction for GitHub {
     fn get_repos(&self) -> Vec<Repo> {
         let mut output = HashSet::new();
         for page in 0.. {
             let request = self.client.get()
                 .custom_endpoint(&format!("orgs/{}/repos?page={}", self.org, page))
-                .execute::<Vec<Repo>>();
+                .execute::<Vec<GithubRepo>>();
 
             if let Ok((_, _, Some(repos))) = request {
                 if repos.len() > 0 {
                     for repo in repos {
-                        output.insert(repo);
+                        output.insert(Repo {
+                            name: repo.name,
+                            html_url: repo.html_url,
+                            ssh_url: repo.ssh_url,
+                            namespace: "".into()
+                        });
                     }
                 } else {
                     break
diff --git a/src/gitlab_impl.rs b/src/gitlab_impl.rs
index f83c6848c58c7531c4ba8842b849b341ec5fc80b..6d3670637f569791f115ae5cb3cad3419d71cb48 100644
--- a/src/gitlab_impl.rs
+++ b/src/gitlab_impl.rs
@@ -10,7 +10,8 @@ impl GitAction for Gitlab {
                 repos.push(Repo {
                     name: project.name,
                     html_url: project.http_url_to_repo,
-                    ssh_url: project.ssh_url_to_repo
+                    ssh_url: project.ssh_url_to_repo,
+                    namespace: project.namespace.full_path,
                 })
             }
         }
diff --git a/src/main.rs b/src/main.rs
index 1e88799839253269817c1ddfc4d7c9c689a182df..b9beb6cbefc7d7044deaa77f3b937715bb319122 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -34,15 +34,12 @@ fn main() {
             .long("force")
             .short("f"))
         .subcommand(SubCommand::with_name("gitlab")
-            .arg(Arg::with_name("DOMAIN")
-                .required(true))
-            .arg(Arg::with_name("ACTION")
-                .required(true)))
+            .arg(Arg::with_name("DOMAIN").required(true))
+            .arg(Arg::with_name("NAMESPACE").required(true))
+            .arg(Arg::with_name("ACTION").required(true)))
         .subcommand(SubCommand::with_name("github")
-            .arg(Arg::with_name("DOMAIN")
-                .required(true))
-            .arg(Arg::with_name("ACTION")
-                .required(true)))
+            .arg(Arg::with_name("DOMAIN").required(true))
+            .arg(Arg::with_name("ACTION").required(true)))
         .get_matches();
 
     let config = match Config::new() {
@@ -56,57 +53,57 @@ fn main() {
     let flags = if matches.occurrences_of("ssh") > 0 { 0b01 } else { 0b00 }
         + if matches.occurrences_of("force") > 0 { 0b10 } else { 0b00 };
 
-    let (source, org, action) = if let Some(matches) = matches.subcommand_matches("gitlab") {
-        (GitService::GitLab, matches.value_of("DOMAIN").unwrap(), matches.value_of("ACTION").unwrap())
+    let (source, org, action, ns) = if let Some(matches) = matches.subcommand_matches("gitlab") {
+        (
+            GitService::GitLab,
+            matches.value_of("DOMAIN").unwrap(),
+            matches.value_of("ACTION").unwrap(),
+            matches.value_of("NAMESPACE").unwrap_or("")
+        )
     } else if let Some(matches) = matches.subcommand_matches("github") {
-        (GitService::GitHub, matches.value_of("DOMAIN").unwrap(), matches.value_of("ACTION").unwrap())
+        (
+            GitService::GitHub,
+            matches.value_of("DOMAIN").unwrap(),
+            matches.value_of("ACTION").unwrap(),
+            ""
+        )
     } else {
         eprintln!("no subcommand provided");
         exit(1);
     };
 
-    let authenticated: Box<GitAction> = match source {
-        GitService::GitHub => {
-            let token = match config.github {
+    macro_rules! client {
+        ($name:tt, $token:expr) => {{
+            let token = match $token {
                 Some(token) => token,
                 None => {
-                    eprintln!("no GitHub token provided");
+                    eprintln!("no {} token provided", stringify!($name));
                     exit(1);
                 }
             };
 
-            match GitHub::new(org.to_owned(), token) {
+            match $name::new(org.to_owned(), token) {
                 Ok(client) => Box::new(client),
                 Err(why) => {
                     eprintln!("unable to authenticate client: {}", why);
                     exit(1);
                 }
             }
-        },
-        GitService::GitLab => {
-            let token = match config.gitlab {
-                Some(token) => token,
-                None => {
-                    eprintln!("no GitLab token provided");
-                    exit(1);
-                }
-            };
 
-            match Gitlab::new(org.to_owned(), token) {
-                Ok(client) => Box::new(client),
-                Err(why) => {
-                    eprintln!("unable to authenticate client: {}", why);
-                    exit(1);
-                }
-            }
-        }
+
+        }};
+    }
+
+    let authenticated: Box<GitAction> = match source {
+        GitService::GitHub => client!(GitHub, config.github),
+        GitService::GitLab => client!(Gitlab, config.gitlab),
     };
 
     match Action::from(action) {
-        Ok(Action::List) => authenticated.list(),
-        Ok(Action::Clone) => authenticated.clone(flags),
-        Ok(Action::Pull) => authenticated.pull(flags),
-        Ok(Action::Checkout) => authenticated.checkout(flags),
+        Ok(Action::List) => authenticated.list(ns),
+        Ok(Action::Clone) => authenticated.clone(flags, ns),
+        Ok(Action::Pull) => authenticated.pull(flags, ns),
+        Ok(Action::Checkout) => authenticated.checkout(flags, ns),
         Err(cmd) => {
             eprintln!("{} is not a valid command", cmd);
             exit(1);