Make the CLI point users at the real install source

The next repo-local backlog item was ROADMAP #70: users could
mistake third-party pages or the deprecated `cargo install
claw-code` path for the official install route. The CLI now
surfaces the source of truth directly in `claw doctor` and
`claw --help`, and the roadmap closeout records the change.

Constraint: Keep the fix inside repo-local Rust CLI surfaces instead of relying on docs alone
Rejected: Close #70 with README-only wording | the bug was user-facing CLI ambiguity, so the warning needed to appear in runtime help/doctor output
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If install guidance changes later, update both the doctor check payload and the help-text warning together
Tested: cargo fmt --all --check; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace; architect review APPROVE
Not-tested: Third-party websites outside this repo that may still present stale install instructions
This commit is contained in:
Yeachan-Heo
2026-04-12 04:50:03 +00:00
parent 26b89e583f
commit 3b806702e7
3 changed files with 69 additions and 3 deletions

View File

@@ -78,6 +78,9 @@ const INTERNAL_PROGRESS_HEARTBEAT_INTERVAL: Duration = Duration::from_secs(3);
const POST_TOOL_STALL_TIMEOUT: Duration = Duration::from_secs(10);
const PRIMARY_SESSION_EXTENSION: &str = "jsonl";
const LEGACY_SESSION_EXTENSION: &str = "json";
const OFFICIAL_REPO_URL: &str = "https://github.com/ultraworkers/claw-code";
const OFFICIAL_REPO_SLUG: &str = "ultraworkers/claw-code";
const DEPRECATED_INSTALL_COMMAND: &str = "cargo install claw-code";
const LATEST_SESSION_REFERENCE: &str = "latest";
const SESSION_REFERENCE_ALIASES: &[&str] = &[LATEST_SESSION_REFERENCE, "last", "recent"];
const CLI_OPTION_SUGGESTIONS: &[&str] = &[
@@ -1477,6 +1480,7 @@ fn render_doctor_report() -> Result<DoctorReport, Box<dyn std::error::Error>> {
checks: vec![
check_auth_health(),
check_config_health(&config_loader, config.as_ref()),
check_install_source_health(),
check_workspace_health(&context),
check_sandbox_health(&context.sandbox_status),
check_system_health(&cwd, config.as_ref().ok()),
@@ -1764,6 +1768,36 @@ fn check_config_health(
}
}
fn check_install_source_health() -> DiagnosticCheck {
DiagnosticCheck::new(
"Install source",
DiagnosticLevel::Ok,
format!(
"official source of truth is {OFFICIAL_REPO_SLUG}; avoid `{DEPRECATED_INSTALL_COMMAND}`"
),
)
.with_details(vec![
format!("Official repo {OFFICIAL_REPO_URL}"),
"Recommended path build from this repo or use the upstream binary documented in README.md"
.to_string(),
format!(
"Deprecated crate `{DEPRECATED_INSTALL_COMMAND}` installs a deprecated stub and does not provide the `claw` binary"
)
.to_string(),
])
.with_data(Map::from_iter([
("official_repo".to_string(), json!(OFFICIAL_REPO_URL)),
(
"deprecated_install".to_string(),
json!(DEPRECATED_INSTALL_COMMAND),
),
(
"recommended_install".to_string(),
json!("build from source or follow the upstream binary instructions in README.md"),
),
]))
}
fn check_workspace_health(context: &StatusContext) -> DiagnosticCheck {
let in_repo = context.project_root.is_some();
DiagnosticCheck::new(
@@ -8111,6 +8145,11 @@ fn print_help_to(out: &mut impl Write) -> io::Result<()> {
out,
" Diagnose local auth, config, workspace, and sandbox health"
)?;
writeln!(out, " Source of truth: {OFFICIAL_REPO_SLUG}")?;
writeln!(
out,
" Warning: do not `{DEPRECATED_INSTALL_COMMAND}` (deprecated stub)"
)?;
writeln!(out, " claw dump-manifests [--manifests-dir PATH]")?;
writeln!(out, " claw bootstrap-plan")?;
writeln!(out, " claw agents")?;
@@ -8200,6 +8239,11 @@ fn print_help_to(out: &mut impl Write) -> io::Result<()> {
writeln!(out, " claw mcp show my-server")?;
writeln!(out, " claw /skills")?;
writeln!(out, " claw doctor")?;
writeln!(out, " source of truth: {OFFICIAL_REPO_URL}")?;
writeln!(
out,
" do not run `{DEPRECATED_INSTALL_COMMAND}` — it installs a deprecated stub"
)?;
writeln!(out, " claw init")?;
writeln!(out, " claw export")?;
writeln!(out, " claw export conversation.md")?;
@@ -10082,6 +10126,8 @@ mod tests {
assert!(help.contains("claw mcp"));
assert!(help.contains("claw skills"));
assert!(help.contains("claw /skills"));
assert!(help.contains("ultraworkers/claw-code"));
assert!(help.contains("cargo install claw-code"));
assert!(!help.contains("claw login"));
assert!(!help.contains("claw logout"));
}

View File

@@ -209,7 +209,7 @@ fn doctor_and_resume_status_emit_json_when_requested() {
assert!(summary["failures"].as_u64().is_some());
let checks = doctor["checks"].as_array().expect("doctor checks");
assert_eq!(checks.len(), 5);
assert_eq!(checks.len(), 6);
let check_names = checks
.iter()
.map(|check| {
@@ -221,7 +221,27 @@ fn doctor_and_resume_status_emit_json_when_requested() {
.collect::<Vec<_>>();
assert_eq!(
check_names,
vec!["auth", "config", "workspace", "sandbox", "system"]
vec![
"auth",
"config",
"install source",
"workspace",
"sandbox",
"system"
]
);
let install_source = checks
.iter()
.find(|check| check["name"] == "install source")
.expect("install source check");
assert_eq!(
install_source["official_repo"],
"https://github.com/ultraworkers/claw-code"
);
assert_eq!(
install_source["deprecated_install"],
"cargo install claw-code"
);
let workspace = checks