app
Adom Shotlog
Public Made by Adomby adom
See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is
use std::sync::Arc;
use crate::store::Store;
/// Spawn an async task to describe an image via claude CLI and update the entry.
pub fn describe_async(
store: Arc<Store>,
channel: String,
entry_id: u64,
image_path: String,
) {
tokio::spawn(async move {
match call_claude(&image_path).await {
Ok(desc) => {
store.update_description(&channel, entry_id, desc).await;
}
Err(e) => {
eprintln!("[shotlog] Claude describe failed: {e}");
}
}
});
}
async fn call_claude(image_path: &str) -> Result<String, String> {
let prompt = "Describe this screenshot in one sentence. Be specific about what's shown. No preamble.";
let cmd_str = format!("claude -p \"{}\" --model haiku --image {}", prompt, image_path);
eprintln!("[shotlog] Running: {cmd_str}");
let output = tokio::process::Command::new("claude")
.args([
"-p", prompt,
"--model", "haiku",
"--image", image_path,
])
.output()
.await
.map_err(|e| format!("Failed to run claude CLI: {e}"))?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(format!("claude CLI failed: {stderr}"));
}
let desc = String::from_utf8_lossy(&output.stdout).trim().to_string();
if desc.is_empty() {
Err("Empty response from claude CLI".into())
} else {
Ok(desc)
}
}