apparently i lost that old source code so here we go again
diff --git a/Cargo.toml b/Cargo.toml
index cdad101..5147943 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,18 +20,29 @@
 name = "tuf"
 path = "./src/lib.rs"
 
+[[bin]]
+name = "tuf"
+path = "./src/bin/tuf.rs"
+required-features = ["cli"]
+
+[features]
+cli = ["clap", "lazy_static"]
+
 [dependencies]
 chrono = { version = "0.4", features = [ "serde" ] }
+clap = { version = "2", optional = true }
 data-encoding = "2.0.0-rc.2"
 derp = "0.0.10"
 hyper = "0.10"
 itoa = "0.4"
+lazy_static = { version = "1", optional = true }
 log = "0.4"
 ring = { version = "0.12", features = [ "rsa_signing" ] }
 serde = "1"
 serde_derive = "1"
 serde_json = "1"
 tempfile = "3"
+toml = "0.4"
 untrusted = "0.5"
 
 [dev-dependencies]
diff --git a/src/bin/tuf.rs b/src/bin/tuf.rs
new file mode 100644
index 0000000..fae30c8
--- /dev/null
+++ b/src/bin/tuf.rs
@@ -0,0 +1,117 @@
+extern crate clap;
+extern crate hyper;
+#[macro_use]
+extern crate lazy_static;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+extern crate toml;
+extern crate tuf;
+
+use clap::{App, ArgMatches, Arg, AppSettings, SubCommand};
+use hyper::client::Client as HttpClient;
+use std::env;
+use std::ffi::OsStr;
+use std::fs::File;
+use std::io::{self, Write, Read};
+use std::path::PathBuf;
+
+use tuf::Result;
+use tuf::error::Error;
+use tuf::client::{Config, Client, DefaultTranslator};
+use tuf::interchange::Json;
+use tuf::metadata::TargetPath;
+use tuf::repository::{FileSystemRepository, HttpRepository};
+
+lazy_static! {
+    static ref HOME_DIR: Option<PathBuf> = env::home_dir().map(|p| p.join(".tuf"));
+}
+
+#[derive(Deserialize)]
+struct CliConfig {
+    config_version: u32,
+    remote: String,
+}
+
+fn main() {
+    match run_main(parser().get_matches()) {
+        Ok(()) => std::process::exit(0),
+        Err(e) => {
+            writeln!(&mut io::stderr(), "{:?}", e).unwrap();
+            std::process::exit(1);
+        }
+    }
+}
+
+fn parser<'a, 'b>() -> App<'a, 'b> {
+    App::new("tuf")
+        .version(env!("CARGO_PKG_VERSION"))
+        .about("Authenticate and download packages")
+        .settings(&[AppSettings::SubcommandRequiredElseHelp])
+        .arg({
+            let arg = Arg::with_name("home")
+             .help("Set the TUF home directory")
+             .short("H")
+             .long("home")
+             .takes_value(true);
+
+            // TODO is this a sane way to do this?
+            match *HOME_DIR {
+                Some(ref home) => arg.default_value_os(home.as_os_str()),
+                None => arg.required(true),
+            }
+        })
+        .subcommand(
+            SubCommand::with_name("fetch")
+                .about("Fetch a target.")
+                .arg(Arg::with_name("target")
+                     .help("Name of the target")
+                     .takes_value(true)
+                     .required(true)
+                )
+        )
+
+}
+
+fn run_main(matches: ArgMatches) -> Result<()> {
+    let home = matches.value_of_os("home").unwrap();
+
+    let mut buf = Vec::new();
+    let mut file = File::open(PathBuf::from(home).join("config.toml"))?;
+    file.read_to_end(&mut buf)?;
+    let cli_config: CliConfig = toml::from_slice(&buf).unwrap(); // TODO unwrap
+
+    if cli_config.config_version > 1 {
+        return Err(Error::Opaque(format!("Invalid config version: {}", cli_config.config_version)))
+    }
+
+    match matches.subcommand() {
+        ("fetch", Some(args)) => fetch_target(home, cli_config, args),
+        _ => unreachable!(),
+    }
+}
+
+fn fetch_target(home: &OsStr, cli_config: CliConfig, args: &ArgMatches) -> Result<()> {
+    let mut client = init_client(home, &cli_config)?;
+    client.update_local()?;
+    client.update_remote()?;
+    client.fetch_target(&TargetPath::new(args.value_of("target").unwrap().to_string())?)?;
+    Ok(())
+}
+
+fn init_client(home: &OsStr, cli_config: &CliConfig) -> Result<Client<Json, FileSystemRepository<Json>, HttpRepository<Json>, DefaultTranslator>> {
+    let config = Config::default();
+    let local = FileSystemRepository::<Json>::new(PathBuf::from(home));
+    let remote = HttpRepository::<Json>::new(cli_config.remote.parse()?, HttpClient::new(), None, None);
+    Client::new(config, local, remote)
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_parser() {
+        let _ = parser();
+    }
+}