noosphere_cli/native/
cli.rs

1//! Declarative definition for the end-user-facing CLI
2
3use noosphere_core::data::Did;
4
5use std::net::IpAddr;
6
7use clap::Parser;
8use clap::Subcommand;
9use url::Url;
10
11#[allow(missing_docs)]
12#[derive(Debug, Parser)]
13#[clap(name = "orb")]
14#[clap(about = "A CLI tool for saving, syncing and sharing content to the Noosphere", long_about = Some(
15r#"The orb CLI tool is a utility for saving, syncing and sharing content to the
16Noosphere. In practical terms, this means it helps you with tasks such as key
17management, creating and updating spheres, managing acccess to said spheres and
18publishing the contents of those spheres to public networks."#))]
19pub struct Cli {
20    #[clap(subcommand)]
21    pub command: OrbCommand,
22}
23
24#[allow(missing_docs)]
25#[derive(Debug, Subcommand)]
26pub enum OrbCommand {
27    Key {
28        #[clap(subcommand)]
29        command: KeyCommand,
30    },
31
32    Sphere {
33        #[clap(subcommand)]
34        command: SphereCommand,
35    },
36
37    /// Display version information for this build of the CLI
38    Version {
39        /// Display extra build and git metadata
40        #[clap(short, long)]
41        verbose: bool,
42    },
43
44    /// Summon a gateway geist to manage the local sphere; it will accept
45    /// push, fetch and other REST actions from any clients that are authorized
46    /// to operate on its counterpart sphere. When it receives changes to its
47    /// counterpart sphere, it will perform various actions such as publishing
48    /// and/or querying the Noosphere Name System, generating static HTML and/or
49    /// updating its own sphere with various related information of interest to
50    /// the counterpart sphere
51    Serve {
52        /// Optional origin to allow CORS for
53        #[clap(short, long)]
54        cors_origin: Option<Url>,
55
56        /// URL of a Kubo Gateway RPC API
57        #[clap(short = 'I', long, default_value = "http://127.0.0.1:5001")]
58        ipfs_api: Url,
59
60        /// URL for a Noosphere name system RPC API
61        #[clap(short = 'N', long, default_value = "http://127.0.0.1:6667")]
62        name_resolver_api: Url,
63
64        /// The IP address of the interface that the gateway should bind to
65        #[clap(short, long, default_value = "127.0.0.1")]
66        interface: IpAddr,
67
68        /// The port that the gateway should listen on
69        #[clap(short, long, default_value = "4433")]
70        port: u16,
71
72        /// If set, the amount of memory that the storage provider may use
73        /// for caching in bytes.
74        #[clap(long)]
75        storage_memory_cache_limit: Option<usize>,
76    },
77}
78
79/// Create and securely manage personal keys
80#[derive(Debug, Subcommand)]
81pub enum KeyCommand {
82    /// Generate and securely store a new named key; this key is the analog of
83    /// a user account in the Noosphere.
84    Create {
85        /// The pet name for the newly created key; you will refer to it by this
86        /// name when using it in other commands
87        name: String,
88    },
89
90    /// Print the pet name and DID for all available keys
91    #[clap(alias = "ls")]
92    List {
93        /// Output the list of available keys as formatted JSON
94        #[clap(short = 'j', long)]
95        as_json: bool,
96    },
97}
98
99/// Create a new sphere or connect another device to an existing one
100#[derive(Debug, Subcommand)]
101pub enum SphereCommand {
102    /// Initialize a new sphere and assign a key as its owner
103    Create {
104        /// The pet name of a key to assign as the owner of the sphere
105        #[clap(short = 'k', long)]
106        owner_key: String,
107    },
108
109    /// Join an existing sphere by its ID and set up a local working copy
110    Join {
111        /// The pet name of a key to use when requesting access to the sphere
112        #[clap(short = 'k', long)]
113        local_key: String,
114
115        /// The URL for a gateway API host that the owner key of this sphere is authorized to use
116        #[clap(short = 'g', long)]
117        gateway_url: Url,
118
119        /// The identity of the authorization that allows the specified key
120        /// to join the sphere (if already known)
121        #[clap(short = 'a', long)]
122        authorization: Option<String>,
123
124        /// The identity of an existing sphere to join
125        id: Did,
126
127        /// The maximum depth to traverse through followed spheres when
128        /// rendering updates
129        #[clap(short = 'd', long)]
130        render_depth: Option<u32>,
131    },
132
133    /// Show details about files in the sphere directory that have changed since
134    /// the last time the sphere was saved
135    Status {
136        /// Only output the orb id
137        #[clap(long)]
138        id: bool,
139    },
140
141    /// Saves changed files to a sphere, creating and signing a new revision in
142    /// the process; does nothing if there have been no changes to the files
143    /// since the last revision
144    Save {
145        /// The maximum depth to traverse through followed spheres when
146        /// rendering updates
147        #[clap(short = 'd', long)]
148        render_depth: Option<u32>,
149    },
150
151    /// Synchronizes the local sphere with the copy in a configured gateway;
152    /// note that this is a "conflict-free" sync that may cause local changes
153    /// to be overwritten in cases where two or more clients have made changes
154    /// to the same files
155    Sync {
156        /// Automatically retry the attempt to sync this number of times
157        #[clap(short = 'r', long, default_value = "0")]
158        auto_retry: u32,
159
160        /// The maximum depth to traverse through followed spheres when
161        /// rendering updates
162        #[clap(short = 'd', long)]
163        render_depth: Option<u32>,
164    },
165
166    /// Force a render of local sphere content as well as the peer graph; note
167    /// that this will overwrite any unsaved changes to local sphere content
168    Render {
169        /// The maximum depth to traverse through followed spheres when
170        /// rendering updates
171        #[clap(short = 'd', long)]
172        render_depth: Option<u32>,
173    },
174
175    /// Print a changelog of sphere in a human readable format
176    History,
177
178    #[allow(missing_docs)]
179    Follow {
180        #[clap(subcommand)]
181        command: FollowCommand,
182    },
183
184    #[allow(missing_docs)]
185    Config {
186        #[clap(subcommand)]
187        command: ConfigCommand,
188    },
189
190    #[allow(missing_docs)]
191    Auth {
192        #[clap(subcommand)]
193        command: AuthCommand,
194    },
195}
196
197/// Read and manage configuration values for a local sphere
198#[derive(Debug, Subcommand)]
199pub enum ConfigCommand {
200    /// Set a configuration value for the local sphere
201    Set {
202        #[allow(missing_docs)]
203        #[clap(subcommand)]
204        command: ConfigSetCommand,
205    },
206    /// Retrieve a configuration value if one is set
207    Get {
208        #[allow(missing_docs)]
209        #[clap(subcommand)]
210        command: ConfigGetCommand,
211    },
212}
213
214/// Write local-only metadata configuration related to this sphere
215#[derive(Debug, Subcommand)]
216pub enum ConfigSetCommand {
217    /// Configure the URL of the gateway to use for publishing and sync
218    GatewayUrl {
219        /// The URL for a gateway API host that the owner key of this sphere is authorized to use
220        url: Url,
221    },
222
223    /// If you are configuring your local sphere, the "counterpart" is the
224    /// gateway's sphere DID. If you are configuring a gateway's sphere, the
225    /// "counterpart" is the DID of your local sphere.
226    Counterpart {
227        /// The sphere identity (as a DID) of the counterpart
228        did: String,
229    },
230}
231
232/// Read local-only metadata configuration related to this sphere
233#[derive(Debug, Subcommand)]
234pub enum ConfigGetCommand {
235    /// Read the configured gateway URL
236    GatewayUrl,
237
238    /// Read the configured counterpart DID
239    Counterpart,
240}
241
242/// Manage the devices/keys that are allowed to access this sphere
243#[derive(Debug, Subcommand)]
244pub enum AuthCommand {
245    /// Authorize a key to work on the sphere in the current directory
246    Add {
247        /// The DID of the key to authorize
248        did: Did,
249
250        /// An optional name to give the key; if one is not specified, a random
251        /// one will be assigned
252        #[clap(short = 'n', long)]
253        name: Option<String>,
254    },
255
256    /// Print the name and DID for all keys that the owner has authorized
257    /// to work on this sphere
258    List {
259        /// Output the list of authorized keys as formatted JSON
260        #[clap(short = 'j', long)]
261        as_json: bool,
262
263        /// Format the authorizations as a tree based on ancestry
264        #[clap(short = 't', long)]
265        tree: bool,
266    },
267
268    /// Revoke authorization to work on the sphere from a specified key
269    Revoke {
270        /// The name of a key to revoke authorization for
271        name: String,
272    },
273
274    /// Rotate key authority from one key to another
275    Rotate {},
276}
277
278/// Follow and/or unfollow other spheres
279#[derive(Debug, Subcommand)]
280pub enum FollowCommand {
281    /// Follow a sphere, assigning it a personalized nickname
282    Add {
283        /// A personalized nickname for the sphere you are following
284        name: Option<String>,
285
286        /// The sphere ID that you wish to follow
287        #[clap(short = 'i', long)]
288        sphere_id: Option<Did>,
289    },
290
291    /// Unfollow a sphere, either by nickname or by sphere ID
292    Remove {
293        /// A short name of a sphere that you wish to unfollow. If you follow
294        /// the same sphere by multiple names, this will only remove the name
295        /// you specify
296        #[clap(short = 'n', long)]
297        by_name: Option<String>,
298
299        /// The sphere ID that you wish to unfollow. If you follow this sphere
300        /// by multiple names, all of them will be removed at once.
301        #[clap(short = 'i', long)]
302        by_sphere_id: Option<Did>,
303    },
304
305    /// Rename a sphere that you currently follow to something new
306    Rename {
307        /// The current nickname of a sphere that you follow
308        from: String,
309
310        /// The preferred nickname to rename the sphere to
311        #[clap(short = 't', long)]
312        to: Option<String>,
313    },
314
315    /// Show a list of all the spheres that you follow
316    List {
317        /// Output the list of peers as formatted JSON
318        #[clap(short = 'j', long)]
319        as_json: bool,
320    },
321}