Skip to content

Commit 498e53f

Browse files
committed
Clean up status and install messages
1 parent b7cdbcd commit 498e53f

1 file changed

Lines changed: 82 additions & 37 deletions

File tree

src/skill.rs

Lines changed: 82 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ fn download_and_extract() -> Result<(), String> {
9595
return Err(format!("error downloading skill: HTTP {}", resp.status()));
9696
}
9797

98-
let bytes = resp.bytes().map_err(|e| format!("error reading response: {e}"))?;
98+
let bytes = resp
99+
.bytes()
100+
.map_err(|e| format!("error reading response: {e}"))?;
99101

100102
// Extract into ~/.hotdata/skills/
101103
let store_dir = home_dir().join(".hotdata").join("skills");
@@ -104,9 +106,15 @@ fn download_and_extract() -> Result<(), String> {
104106
let gz = flate2::read::GzDecoder::new(std::io::Cursor::new(bytes));
105107
let mut archive = tar::Archive::new(gz);
106108

107-
for entry in archive.entries().map_err(|e| format!("error reading archive: {e}"))? {
109+
for entry in archive
110+
.entries()
111+
.map_err(|e| format!("error reading archive: {e}"))?
112+
{
108113
let mut entry = entry.map_err(|e| format!("error reading archive entry: {e}"))?;
109-
let path = entry.path().map_err(|e| format!("error reading entry path: {e}"))?.into_owned();
114+
let path = entry
115+
.path()
116+
.map_err(|e| format!("error reading entry path: {e}"))?
117+
.into_owned();
110118

111119
let rel = match path.strip_prefix("skills/") {
112120
Ok(r) if !r.as_os_str().is_empty() => r.to_path_buf(),
@@ -117,13 +125,14 @@ fn download_and_extract() -> Result<(), String> {
117125
if let Some(parent) = dest.parent() {
118126
fs::create_dir_all(parent).map_err(|e| format!("error creating directory: {e}"))?;
119127
}
120-
entry.unpack(&dest).map_err(|e| format!("error extracting {}: {e}", rel.display()))?;
128+
entry
129+
.unpack(&dest)
130+
.map_err(|e| format!("error extracting {}: {e}", rel.display()))?;
121131
}
122132

123133
Ok(())
124134
}
125135

126-
127136
fn copy_dir_recursive(src: &PathBuf, dst: &PathBuf) -> Result<(), String> {
128137
fs::create_dir_all(dst).map_err(|e| format!("error creating directory: {e}"))?;
129138
for entry in fs::read_dir(src).map_err(|e| format!("error reading directory: {e}"))? {
@@ -147,8 +156,7 @@ fn ensure_symlink_or_copy(src: &PathBuf, link_path: &PathBuf) -> Result<bool, St
147156
// Remove any existing symlink or directory so we can (re)create it
148157
if link_path.symlink_metadata().is_ok() {
149158
if link_path.is_symlink() {
150-
fs::remove_file(link_path)
151-
.map_err(|e| format!("error removing old symlink: {e}"))?;
159+
fs::remove_file(link_path).map_err(|e| format!("error removing old symlink: {e}"))?;
152160
} else {
153161
fs::remove_dir_all(link_path)
154162
.map_err(|e| format!("error removing old directory: {e}"))?;
@@ -198,7 +206,11 @@ pub fn install_project() {
198206
match read_installed_version() {
199207
Some(ref v) if *v >= current => {}
200208
Some(ref v) => {
201-
println!("{}", format!("Global skill is outdated (v{v}), downloading v{current} first...").yellow());
209+
println!(
210+
"{}",
211+
format!("Global skill is outdated (v{v}), downloading v{current} first...")
212+
.yellow()
213+
);
202214
if let Err(e) = download_and_extract() {
203215
eprintln!("{}", e.red());
204216
std::process::exit(1);
@@ -218,26 +230,43 @@ pub fn install_project() {
218230

219231
// Always copy (not symlink) from store to .agents/skills/hotdata-cli
220232
if project_agents.exists() {
221-
fs::remove_dir_all(&project_agents)
222-
.unwrap_or_else(|e| { eprintln!("{}", format!("error removing existing directory: {e}").red()); std::process::exit(1); });
233+
fs::remove_dir_all(&project_agents).unwrap_or_else(|e| {
234+
eprintln!(
235+
"{}",
236+
format!("error removing existing directory: {e}").red()
237+
);
238+
std::process::exit(1);
239+
});
223240
}
224241
if let Some(parent) = project_agents.parent() {
225-
fs::create_dir_all(parent).unwrap_or_else(|e| { eprintln!("{}", format!("error creating directory: {e}").red()); std::process::exit(1); });
242+
fs::create_dir_all(parent).unwrap_or_else(|e| {
243+
eprintln!("{}", format!("error creating directory: {e}").red());
244+
std::process::exit(1);
245+
});
226246
}
227-
copy_dir_recursive(&store_path, &project_agents).unwrap_or_else(|e| { eprintln!("{}", e.red()); std::process::exit(1); });
247+
copy_dir_recursive(&store_path, &project_agents).unwrap_or_else(|e| {
248+
eprintln!("{}", e.red());
249+
std::process::exit(1);
250+
});
251+
252+
let rel_agents = project_agents.strip_prefix(&cwd).unwrap_or(&project_agents);
228253

229-
println!("{}", format!("Skill installed to project (v{current}).").green());
230-
println!("{:<20}{}", "Location:", project_agents.display().to_string().cyan());
254+
println!(
255+
"{}",
256+
format!("Skill installed to project (v{current}).").green()
257+
);
258+
println!("{:<20}{}", "Location:", rel_agents.display().to_string().cyan());
231259

232260
// For .claude and .pi in cwd: symlink (fallback copy) from .agents/skills/hotdata-cli
233261
for root in AGENT_ROOTS {
234262
let root_path = cwd.join(root);
235263
if root_path.exists() {
236264
let link_path = root_path.join("skills").join(SKILL_NAME);
265+
let rel_link = link_path.strip_prefix(&cwd).unwrap_or(&link_path);
237266
match ensure_symlink_or_copy(&project_agents, &link_path) {
238-
Ok(true) => println!("{:<20}{}", format!("~/{root}:"), link_path.display().to_string().cyan()),
239-
Ok(false) => println!("{:<20}{} (copied)", format!("~/{root}:"), link_path.display().to_string().cyan()),
240-
Err(e) => eprintln!("{}", format!("~/{root}: failed: {e}").red()),
267+
Ok(true) => println!("{:<20}{}", format!("./{root}:"), rel_link.display().to_string().cyan()),
268+
Ok(false) => println!("{:<20}{} (copied)", format!("./{root}:"), rel_link.display().to_string().cyan()),
269+
Err(e) => eprintln!("{}", format!("./{root}: failed: {e}").red()),
241270
}
242271
}
243272
}
@@ -253,7 +282,11 @@ pub fn install() {
253282
return;
254283
}
255284
Some(ref v) => {
256-
println!("{}", format!("Managed by skills agent — updating from v{v} to v{current}...").yellow());
285+
println!(
286+
"{}",
287+
format!("Managed by skills agent — updating from v{v} to v{current}...")
288+
.yellow()
289+
);
257290
}
258291
None => {
259292
println!("Managed by skills agent — skipping.");
@@ -278,7 +311,10 @@ pub fn install() {
278311

279312
let symlinks = ensure_symlinks();
280313

281-
println!("{}", format!("Skill installed successfully (v{current}).").green());
314+
println!(
315+
"{}",
316+
format!("Skill installed successfully (v{current}).").green()
317+
);
282318
println!("{:<20}{}", "Location:", skill_store_path().display());
283319

284320
for (label, path, result) in &symlinks {
@@ -295,7 +331,6 @@ pub fn status() {
295331
let store_path = skill_store_path();
296332
let current = Version::parse(CURRENT_VERSION).expect("invalid package version");
297333

298-
let managed = is_managed_by_skills_agent();
299334
let installed_version = read_installed_version();
300335
let exists = store_path.exists();
301336

@@ -313,33 +348,43 @@ pub fn status() {
313348

314349
match &installed_version {
315350
Some(v) if *v < current => {
316-
row("Version", &format!("{} (outdated, current is v{current})", v.to_string().yellow()));
351+
row(
352+
"Version",
353+
&format!(
354+
"{} (outdated, current is v{current})",
355+
v.to_string().yellow()
356+
),
357+
);
317358
}
318359
Some(v) => row("Version", &v.to_string().green().to_string()),
319360
None => row("Version", &"unknown".dark_grey().to_string()),
320361
}
321362

322-
row("Location", &store_path.display().to_string().cyan().to_string());
323-
row("Managed by", &if managed { "skills agent".to_string() } else { "direct".dark_grey().to_string() });
324-
325-
// Show symlink status for each agent root
326363
let home = home_dir();
364+
365+
// Collect installed agent skill paths
366+
let agents_path = agents_skill_path();
367+
let mut installed_agents: Vec<String> = Vec::new();
368+
369+
if agents_path.exists() {
370+
installed_agents.push("~/.agents".to_string());
371+
}
327372
for root in AGENT_ROOTS {
328-
let root_path = home.join(root);
329-
let link_path = root_path.join("skills").join(SKILL_NAME);
330-
let label = format!("~/{root}");
331-
332-
if !root_path.exists() {
333-
row(&label, &"not installed".dark_grey().to_string());
334-
} else if link_path.is_symlink() {
335-
row(&label, &link_path.display().to_string().cyan().to_string());
336-
} else if link_path.exists() {
337-
row(&label, &"installed (not symlinked)".yellow().to_string());
338-
} else {
339-
row(&label, &"agent detected, not symlinked".yellow().to_string());
373+
let link_path = home.join(root).join("skills").join(SKILL_NAME);
374+
if link_path.exists() {
375+
installed_agents.push(format!("~/{root}"));
340376
}
341377
}
342378

379+
if installed_agents.is_empty() {
380+
row("Agent Skills", &"none".dark_grey().to_string());
381+
} else {
382+
row(
383+
"Agent Skills Added",
384+
&installed_agents.join(", ").cyan().to_string(),
385+
);
386+
}
387+
343388
if installed_version.map_or(false, |v| v < current) {
344389
println!("\nRun 'hotdata skill install' to update.");
345390
}

0 commit comments

Comments
 (0)