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}