| Crates.io | space-operator-cli |
| lib.rs | space-operator-cli |
| version | 0.10.0 |
| created_at | 2024-10-10 04:28:23.307087+00 |
| updated_at | 2025-12-16 09:05:21.727423+00 |
| description | CLI for Space Operator |
| homepage | https://spaceoperator.com |
| repository | https://github.com/space-operator/flow-backend |
| max_upload_size | |
| id | 1403458 |
| size | 169,699 |
CLI for Space Operator.
Table of contents:
Install using cargo install:
cargo install space-operator-cli --force
Binary name: spo
$ spo --help
Usage: spo [OPTIONS] [COMMAND]
Commands:
login Login to Space Operator using API key
start Start flow-server [aliases: s]
node Manage your nodes [aliases: n]
generate Generate various things [aliases: g]
run Run various binaries
help Print this message or the help of the given subcommand(s)
Options:
--url <URL> URL of flow-server to use (default: https://dev-api.spaceoperator.com)
-h, --help Print help
Run spo login:
$ spo login
Go to https://spaceoperator.com/dashboard/profile/apikey go generate a key
Please paste your API key below
Enter your API key to login.
Clone flow-backend repository:
git clone https://github.com/space-operator/flow-backend
cd into flow-backend and run spo start:
cd flow-backend
spo start config.jsonc
Start a local docker deployment as instructed in docker/README.md.
Stop the docker flow-server:
docker compose down flow-server
Build and start a flow-server that connects to local docker database:
spo start --docker
Make sure you are inside flow-backend repository.
Generate with spo node new:
$ spo node new
could not determine which package to update
use `-p` option to specify a package
available packages:
client
flow-lib
spo-helius
flow-value
space-lib
cmds-deno
command-rpc
srpc
cmds-pdg
pdg-common
cmds-solana
cmds-std
db
flow
rhai-script
space-wasm
utils
flow-server
Because our workspace have several packages, you must specify one of them to use (our CLI can automatically choose one if you are inside one of them).
$ spo node new -p cmds-solana
Fill the prompts for node definition, for example:
$ spo node new -p cmds-solana
using package: cmds-solana
enter ? for help
? module path: ?
enter valid Rust module path to save the node (empty to save at root)
? module path:
? node id: transfer
? display name: Transfer
description:
adding node inputs (enter empty name to finish)
? name: fee_payer
? input type: keypair
? optional (true/false): false
? passthrough (true/false): true
adding node inputs (enter empty name to finish)
? name: amount
? input type: decimal
? optional (true/false): false
? passthrough (true/false): false
adding node inputs (enter empty name to finish)
? name:
adding node outputs (enter empty name to finish)
? name: balance
? output type: decimal
? optional (true/false): true
adding node outputs (enter empty name to finish)
? name:
will this node emit Solana instructions? (y/n): y
adding `signature` output
adding `submit` input
adding instruction info: {
"before": [
"balance",
"fee_payer"
],
"signature": "signature",
"after": []
}
writing node definition to crates/cmds-solana/node-definitions/transfer.json
writing code to crates/cmds-solana/src/transfer.rs
updating module crates/cmds-solana/src/lib.rs
upload node (y/n): y
node: transfer
command is not in database
upload? (y/n): y
inserted new node, id=1256
view your node:
https://spaceoperator.com/dashboard/nodes/c334e245-75b4-49fd-93c0-c4b25ab74f70.transfer.0.1
Generated Rust code:
use flow_lib::command::prelude::*;
const NAME: &str = "transfer";
flow_lib::submit!(CommandDescription::new(NAME, | _ | build()));
fn build() -> BuildResult {
const DEFINITION: &str = flow_lib::node_definition!("/transfer.json");
static CACHE: BuilderCache = BuilderCache::new(|| {
CmdBuilder::new(DEFINITION)?.check_name(NAME)
});
Ok(CACHE.clone()?.build(run))
}
#[serde_as]
#[derive(Deserialize, Serialize, Debug)]
pub struct Input {
pub fee_payer: Wallet,
#[serde_as(as = "AsDecimal")]
pub amount: Decimal,
#[serde(default = "value::default::bool_true")]
pub submit: bool,
}
#[serde_as]
#[derive(Deserialize, Serialize, Debug)]
pub struct Output {
#[serde_as(as = "AsDecimal")]
pub balance: Option<Decimal>,
#[serde_as(as = "Option<Signature>")]
pub signature: Option<Signature>,
}
async fn run(mut ctx: Context, input: Input) -> Result<Output, CommandError> {
tracing::info!("input: {:?}", input);
let signature = ctx
.execute(Instructions::default(), value::map! {})
.await?
.signature;
Err(CommandError::msg("unimplemented"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build() {
build().unwrap();
}
#[tokio::test]
async fn test_run() {
let ctx = Context::default();
build().unwrap().run(ctx, ValueSet::new()).await.unwrap_err();
}
}
Then, you can use spo start to run a local flow-server and test your node in flow editor.
If you updated the node definition manually, you can use spo generate input and
spo generate output to generate new type definitions.
For example
spo generate input crates/cmds-solana/node-definitions/nft/v1/mint_v1.json
#[serde_as]
#[derive(Deserialize, Serialize, Debug)]
struct Input {
fee_payer: Wallet,
authority: Option<Wallet>,
#[serde_as(as = "AsPubkey")]
mint_account: Pubkey,
#[serde_as(as = "AsPubkey")]
token_owner: Pubkey,
amount: Option<u64>,
#[serde_as(as = "Option<AsPubkey>")]
delegate_record: Option<Pubkey>,
#[serde_as(as = "Option<AsPubkey>")]
authorization_rules_program: Option<Pubkey>,
#[serde_as(as = "Option<AsPubkey>")]
authorization_rules: Option<Pubkey>,
authorization_data: Option<JsonValue>,
#[serde(default = "value::default::bool_true")]
submit: bool,
}
Use spo node upload to upload new node definition or update existing one.
We only support native node at the moment.
spoThis document contains the help content for the spo command-line program.
Command Overview:
spo↴spo login↴spo start↴spo node↴spo node new↴spo node upload↴spo generate↴spo generate input↴spo generate output↴spo run↴spoUsage: spo [OPTIONS] [COMMAND]
login — Login to Space Operator using API keystart — Start flow-servernode — Manage your nodesgenerate — Generate various thingsrun — Run various binaries--url <URL> — URL of flow-server to use (default: https://dev-api.spaceoperator.com)
spo loginLogin to Space Operator using API key
Usage: spo login
spo startStart flow-server
Usage: spo start [OPTIONS] [CONFIG]
Command Alias: s
<CONFIG> — Path to configuration file--docker — Connect to local Docker instance
--release — Use --release build
spo nodeManage your nodes
Usage: spo node <COMMAND>
Command Alias: n
new — Generate a new node
upload — Upload nodes
spo node newGenerate a new node
Usage: spo node new [OPTIONS]
Command Alias: n
--allow-dirty — Allow dirty git repository
-p, --package <PACKAGE> — Specify which Rust package to add the new node to
spo node uploadUpload nodes
Usage: spo node upload [OPTIONS] <PATH>
Command Alias: u
<PATH> — Path to JSON node definition file--dry-run — Only print diff, don't do anything
--no-confirm — Don't ask for confirmation
spo generateGenerate various things
Usage: spo generate <COMMAND>
Command Alias: g
input — Generate input struct
output — Generate output struct
spo generate inputGenerate input struct
Usage: spo generate input <PATH>
Command Alias: i
<PATH> — Path to node definition file
spo generate outputGenerate output struct
Usage: spo generate output <PATH>
Command Alias: o
<PATH> — Path to node definition file
spo runRun various binaries
Usage: spo run [OPTIONS] <BIN>
<BIN> — Specify binary to run
Possible values: all-cmds-server, deno-cmds-server
--release — Run in release mode
This document was generated automatically by
clap-markdown.