Skip to content

Commit 17ed0ec

Browse files
tliesnhamclaude
andcommitted
Add CLI spinners for prompt parsing and file upload (v0.2.1)
Shows an animated spinner while calling /v1/prompt and while uploading each file, giving users clear feedback that the CLI is working. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 09cb85d commit 17ed0ec

File tree

3 files changed

+101
-4
lines changed

3 files changed

+101
-4
lines changed

Cargo.lock

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mochify-cli"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2024"
55

66
[[bin]]
@@ -15,4 +15,5 @@ tokio = { version = "1", features = ["full"] }
1515
serde = { version = "1", features = ["derive"] }
1616
serde_json = "1"
1717
anyhow = "1"
18+
indicatif = "0.17"
1819
rmcp = { version = "0.16", features = ["server", "macros", "transport-io"] }

src/main.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use anyhow::Result;
66
use api::{MochifyClient, ProcessParams};
77
use clap::Parser;
88
use cli::{Args, Commands};
9+
use indicatif::{ProgressBar, ProgressStyle};
910
use std::path::PathBuf;
11+
use std::time::Duration;
1012

1113
#[tokio::main]
1214
async fn main() -> Result<()> {
@@ -38,8 +40,11 @@ async fn process_files(args: Args) -> Result<()> {
3840

3941
// If a prompt was supplied, resolve params for all files in one request.
4042
let prompt_map = if let Some(ref prompt) = args.prompt {
43+
let sp = spinner("Parsing prompt...");
4144
let paths: Vec<&std::path::Path> = args.files.iter().map(|p| p.as_path()).collect();
42-
Some(client.resolve_prompt(prompt, &paths).await?)
45+
let map = client.resolve_prompt(prompt, &paths).await?;
46+
sp.finish_and_clear();
47+
Some(map)
4348
} else {
4449
None
4550
};
@@ -65,9 +70,17 @@ async fn process_files(args: Args) -> Result<()> {
6570
None => explicit.clone(),
6671
};
6772

73+
let name = file_path.file_name().map(|n| n.to_string_lossy().into_owned()).unwrap_or_default();
74+
let sp = spinner(format!("Uploading {name}..."));
6875
match client.squish(file_path, &params, &out_dir).await {
69-
Ok(out) => println!("{}", out.display()),
70-
Err(e) => eprintln!("Error processing {}: {e:#}", file_path.display()),
76+
Ok(out) => {
77+
sp.finish_and_clear();
78+
println!("{}", out.display());
79+
}
80+
Err(e) => {
81+
sp.finish_and_clear();
82+
eprintln!("Error processing {}: {e:#}", file_path.display());
83+
}
7184
}
7285
}
7386

@@ -86,6 +99,19 @@ fn merge_params(base: ProcessParams, overrides: ProcessParams) -> ProcessParams
8699
}
87100
}
88101

102+
fn spinner(msg: impl Into<String>) -> ProgressBar {
103+
let pb = ProgressBar::new_spinner();
104+
pb.set_style(
105+
ProgressStyle::default_spinner()
106+
.tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"])
107+
.template("{spinner} {msg}")
108+
.unwrap(),
109+
);
110+
pb.set_message(msg.into());
111+
pb.enable_steady_tick(Duration::from_millis(80));
112+
pb
113+
}
114+
89115
async fn run_mcp_server(api_key: Option<String>) -> Result<()> {
90116
use rmcp::ServiceExt;
91117

0 commit comments

Comments
 (0)