diff --git a/client/src/main.rs b/client/src/main.rs
index f90db2f..f539c12 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -3,9 +3,9 @@ use dialoguer::{Confirm, Input};
 use hostsfile::HostsBuilder;
 use indoc::printdoc;
 use shared::{
-    interface_config::InterfaceConfig, prompts, AddCidrContents, AddPeerContents, Association,
-    AssociationContents, Cidr, CidrTree, EndpointContents, Interface, IoErrorContext, Peer,
-    RedeemContents, State, CLIENT_CONFIG_PATH, REDEEM_TRANSITION_WAIT,
+    interface_config::InterfaceConfig, prompts, AddCidrOpts, AddPeerOpts, Association,
+    AssociationContents, Cidr, CidrTree, EndpointContents, InstallOpts, Interface, IoErrorContext,
+    Peer, RedeemContents, State, CLIENT_CONFIG_PATH, REDEEM_TRANSITION_WAIT,
 };
 use std::{
     fmt,
@@ -56,6 +56,9 @@ enum Command {
 
         #[structopt(flatten)]
         hosts: HostsOpt,
+
+        #[structopt(flatten)]
+        opts: InstallOpts,
     },
 
     /// Enumerate all innernet connections.
@@ -107,7 +110,7 @@ enum Command {
         interface: Interface,
 
         #[structopt(flatten)]
-        args: AddPeerContents,
+        opts: AddPeerOpts,
     },
 
     /// Add a new CIDR.
@@ -115,7 +118,7 @@ enum Command {
         interface: Interface,
 
         #[structopt(flatten)]
-        args: AddCidrContents,
+        opts: AddCidrOpts,
     },
 
     /// Disable an enabled peer.
@@ -191,14 +194,20 @@ fn update_hosts_file(
     Ok(())
 }
 
-fn install(invite: &Path, hosts_file: Option<PathBuf>) -> Result<(), Error> {
+fn install(invite: &Path, hosts_file: Option<PathBuf>, opts: InstallOpts) -> Result<(), Error> {
     shared::ensure_dirs_exist(&[*CLIENT_CONFIG_PATH])?;
     let config = InterfaceConfig::from_file(invite)?;
 
-    let iface = Input::with_theme(&*prompts::THEME)
-        .with_prompt("Interface name")
-        .default(config.interface.network_name.clone())
-        .interact()?;
+    let iface = if opts.default_name {
+        config.interface.network_name.clone()
+    } else if let Some(ref iface) = opts.name {
+        iface.clone()
+    } else {
+        Input::with_theme(&*prompts::THEME)
+            .with_prompt("Interface name")
+            .default(config.interface.network_name.clone())
+            .interact()?
+    };
 
     let target_conf = CLIENT_CONFIG_PATH.join(&iface).with_extension("conf");
     if target_conf.exists() {
@@ -217,13 +226,14 @@ fn install(invite: &Path, hosts_file: Option<PathBuf>) -> Result<(), Error> {
 
     fetch(&iface, false, hosts_file)?;
 
-    if Confirm::with_theme(&*prompts::THEME)
-        .with_prompt(&format!(
-            "Delete invitation file \"{}\" now? (It's no longer needed)",
-            invite.to_string_lossy().yellow()
-        ))
-        .default(true)
-        .interact()?
+    if opts.delete_invite
+        || Confirm::with_theme(&*prompts::THEME)
+            .with_prompt(&format!(
+                "Delete invitation file \"{}\" now? (It's no longer needed)",
+                invite.to_string_lossy().yellow()
+            ))
+            .default(true)
+            .interact()?
     {
         std::fs::remove_file(invite).with_path(invite)?;
     }
@@ -473,13 +483,13 @@ fn uninstall(interface: &InterfaceName) -> Result<(), Error> {
     Ok(())
 }
 
-fn add_cidr(interface: &InterfaceName, args: AddCidrContents) -> Result<(), Error> {
+fn add_cidr(interface: &InterfaceName, opts: AddCidrOpts) -> Result<(), Error> {
     let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
     println!("Fetching CIDRs");
     let api = Api::new(&server);
     let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
 
-    let cidr_request = prompts::add_cidr(&cidrs, &args)?;
+    let cidr_request = prompts::add_cidr(&cidrs, &opts)?;
 
     println!("Creating CIDR...");
     let cidr: Cidr = api.http_form("POST", "/admin/cidrs", cidr_request)?;
@@ -499,7 +509,7 @@ fn add_cidr(interface: &InterfaceName, args: AddCidrContents) -> Result<(), Erro
     Ok(())
 }
 
-fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Error> {
+fn add_peer(interface: &InterfaceName, opts: AddPeerOpts) -> Result<(), Error> {
     let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
     let api = Api::new(&server);
 
@@ -509,7 +519,7 @@ fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Erro
     let peers: Vec<Peer> = api.http("GET", "/admin/peers")?;
     let cidr_tree = CidrTree::new(&cidrs[..]);
 
-    if let Some((peer_request, keypair)) = prompts::add_peer(&peers, &cidr_tree, &args)? {
+    if let Some((peer_request, keypair)) = prompts::add_peer(&peers, &cidr_tree, &opts)? {
         println!("Creating peer...");
         let peer: Peer = api.http_form("POST", "/admin/peers", peer_request)?;
         let server_peer = peers.iter().find(|p| p.id == 1).unwrap();
@@ -520,7 +530,7 @@ fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Erro
             &cidr_tree,
             keypair,
             &server.internal_endpoint,
-            &args.save_config,
+            &opts.save_config,
         )?;
     } else {
         println!("exited without creating peer.");
@@ -830,7 +840,11 @@ fn run(opt: Opt) -> Result<(), Error> {
     });
 
     match command {
-        Command::Install { config, hosts } => install(&config, hosts.into())?,
+        Command::Install {
+            config,
+            hosts,
+            opts,
+        } => install(&config, hosts.into(), opts)?,
         Command::Show {
             short,
             tree,
@@ -849,8 +863,8 @@ fn run(opt: Opt) -> Result<(), Error> {
         )?,
         Command::Down { interface } => wg::down(&interface)?,
         Command::Uninstall { interface } => uninstall(&interface)?,
-        Command::AddPeer { interface, args } => add_peer(&interface, args)?,
-        Command::AddCidr { interface, args } => add_cidr(&interface, args)?,
+        Command::AddPeer { interface, opts } => add_peer(&interface, opts)?,
+        Command::AddCidr { interface, opts } => add_cidr(&interface, opts)?,
         Command::DisablePeer { interface } => enable_or_disable_peer(&interface, false)?,
         Command::EnablePeer { interface } => enable_or_disable_peer(&interface, true)?,
         Command::AddAssociation { interface } => add_association(&interface)?,
diff --git a/server/src/main.rs b/server/src/main.rs
index 6435d39..5f5e7a2 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -7,7 +7,7 @@ use ipnetwork::IpNetwork;
 use parking_lot::Mutex;
 use rusqlite::Connection;
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
-use shared::{AddCidrContents, AddPeerContents, IoErrorContext, INNERNET_PUBKEY_HEADER};
+use shared::{AddCidrOpts, AddPeerOpts, IoErrorContext, INNERNET_PUBKEY_HEADER};
 use std::{
     convert::Infallible,
     env,
@@ -64,7 +64,7 @@ enum Command {
         interface: Interface,
 
         #[structopt(flatten)]
-        args: AddPeerContents,
+        args: AddPeerOpts,
     },
 
     /// Add a new CIDR to an existing network.
@@ -72,7 +72,7 @@ enum Command {
         interface: Interface,
 
         #[structopt(flatten)]
-        args: AddCidrContents,
+        args: AddCidrOpts,
     },
 }
 
@@ -237,7 +237,7 @@ fn open_database_connection(
 fn add_peer(
     interface: &InterfaceName,
     conf: &ServerConfig,
-    args: AddPeerContents,
+    args: AddPeerOpts,
 ) -> Result<(), Error> {
     let config = ConfigFile::from_file(conf.config_path(interface))?;
     let conn = open_database_connection(interface, conf)?;
@@ -280,7 +280,7 @@ fn add_peer(
 fn add_cidr(
     interface: &InterfaceName,
     conf: &ServerConfig,
-    args: AddCidrContents,
+    args: AddCidrOpts,
 ) -> Result<(), Error> {
     let conn = open_database_connection(interface, conf)?;
     let cidrs = DatabaseCidr::list(&conn)?;
diff --git a/shared/src/prompts.rs b/shared/src/prompts.rs
index 0934a74..73d7a56 100644
--- a/shared/src/prompts.rs
+++ b/shared/src/prompts.rs
@@ -1,7 +1,7 @@
 use crate::{
     interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
-    AddCidrContents, AddPeerContents, Association, Cidr, CidrContents, CidrTree, Error, Peer,
-    PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
+    AddCidrOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, Error, Peer, PeerContents,
+    PERSISTENT_KEEPALIVE_INTERVAL_SECS,
 };
 use colored::*;
 use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
@@ -32,7 +32,7 @@ pub fn hostname_validator(name: &String) -> Result<(), &'static str> {
 }
 
 /// Bring up a prompt to create a new CIDR. Returns the peer request.
-pub fn add_cidr(cidrs: &[Cidr], request: &AddCidrContents) -> Result<Option<CidrContents>, Error> {
+pub fn add_cidr(cidrs: &[Cidr], request: &AddCidrOpts) -> Result<Option<CidrContents>, Error> {
     let parent_cidr = if let Some(ref parent_name) = request.parent {
         cidrs
             .iter()
@@ -161,7 +161,7 @@ pub fn delete_association<'a>(
 pub fn add_peer(
     peers: &[Peer],
     cidr_tree: &CidrTree,
-    args: &AddPeerContents,
+    args: &AddPeerOpts,
 ) -> Result<Option<(PeerContents, KeyPair)>, Error> {
     let leaves = cidr_tree.leaves();
 
diff --git a/shared/src/types.rs b/shared/src/types.rs
index b205ee4..5615b71 100644
--- a/shared/src/types.rs
+++ b/shared/src/types.rs
@@ -167,7 +167,22 @@ pub struct RedeemContents {
 }
 
 #[derive(Debug, Clone, PartialEq, StructOpt)]
-pub struct AddPeerContents {
+pub struct InstallOpts {
+    /// Set a specific interface name
+    #[structopt(long, conflicts_with = "default-name")]
+    pub name: Option<String>,
+
+    /// Use the network name inside the invitation as the interface name
+    #[structopt(long = "default-name")]
+    pub default_name: bool,
+
+    /// Delete the invitation after a successful install
+    #[structopt(short, long)]
+    pub delete_invite: bool,
+}
+
+#[derive(Debug, Clone, PartialEq, StructOpt)]
+pub struct AddPeerOpts {
     /// Name of new peer
     #[structopt(long)]
     pub name: Option<String>,
@@ -197,7 +212,7 @@ pub struct AddPeerContents {
 }
 
 #[derive(Debug, Clone, PartialEq, StructOpt)]
-pub struct AddCidrContents {
+pub struct AddCidrOpts {
     #[structopt(long)]
     pub name: Option<String>,