diff --git a/Cargo.lock b/Cargo.lock index e35478d..6d1c1a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1430,6 +1430,15 @@ dependencies = [ "pxfm", ] +[[package]] +name = "nanoid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +dependencies = [ + "rand 0.8.5", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -2699,6 +2708,7 @@ dependencies = [ "ed25519-dalek", "image", "libc", + "nanoid", "open", "reqwest", "semver", diff --git a/Cargo.toml b/Cargo.toml index f61345b..946a0b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ url = "2" image = "0.25" sentry = { version = "0.35", default-features = false, features = ["backtrace", "contexts", "tracing", "reqwest", "rustls", "panic"] } uuid = { version = "1", features = ["v4"] } +nanoid = "0.4" [dev-dependencies] tempfile = "3" diff --git a/src/cli/hook.rs b/src/cli/hook.rs index db64779..f6d8fa5 100644 --- a/src/cli/hook.rs +++ b/src/cli/hook.rs @@ -42,6 +42,16 @@ pub fn handle_hook(event: HookEvent, agent: &str) -> Result<()> { fs::create_dir_all(&pid_dir)?; fs::write(pid_dir.join(claude_pid.to_string()), &input.session_id)?; } + + // Generate a share slug and display the session URL + if let Ok(base) = LocalStorage::default_base_dir() { + let slug = nanoid::nanoid!(12); + let slug_dir = base.join("share-slugs"); + if fs::create_dir_all(&slug_dir).is_ok() { + let _ = fs::write(slug_dir.join(&input.session_id), &slug); + } + eprintln!("\u{1f9f5} https://threader.sh/s/{}", slug); + } } if matches!(event, HookEvent::SessionEnd) { if let Some(claude_pid) = crate::process::find_claude_ancestor_pid() { diff --git a/src/sync/uploader.rs b/src/sync/uploader.rs index 752574d..d04db05 100644 --- a/src/sync/uploader.rs +++ b/src/sync/uploader.rs @@ -220,6 +220,17 @@ impl BackgroundUploader { body["repo"] = serde_json::json!(repo); } + // Include client-generated share slug if available + if let Ok(base) = LocalStorage::default_base_dir() { + let slug_path = base.join("share-slugs").join(&entry.session_id); + if let Ok(slug) = fs::read_to_string(&slug_path) { + let slug = slug.trim(); + if !slug.is_empty() { + body["share_slug"] = serde_json::json!(slug); + } + } + } + let url = format!("{}/api/sessions", convex_site_url()); info!("Creating session {} at {}", entry.session_id, url);