{"record":{"id":"db8bebb10d84b405","repo":"pbakaus/impeccable","slug":"could-not-determine-a-target-harness-folder","errorCode":null,"errorMessage":"Could not determine a target harness folder.","messagePattern":"Could not determine a target harness folder\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/skills/src/commands.rs","lineNumber":469,"sourceCode":"/// JS: link(flags)\nfn link(flags: &[String], io: &mut Io) -> R<()> {\n    let (sys, mut prompt) = ctx(io);\n    let force = has_flag(flags, \"--force\");\n    let yes = has_flag(flags, \"-y\") || has_flag(flags, \"--yes\");\n    let source_value = get_flag_value(flags, \"--source\");\n    let providers_value = get_flag_value(flags, \"--providers\");\n    let root = sys.find_project_root();\n\n    let source = match bundle::resolve_link_source(source_value, &root) {\n        Ok(s) => s,\n        Err(e) => {\n            err(io, &e);\n            return Err(Flow::Exit(1));\n        }\n    };\n    let targets = sys.resolve_install_targets(&root, providers_value);\n    if targets.is_empty() {\n        err(io, \"Could not determine a target harness folder.\");\n        err(io, \"Pass one explicitly, e.g. --providers=claude,cursor\");\n        return Err(Flow::Exit(1));\n    }\n    if !yes {\n        out(io, &format!(\"Source checkout: {}\", source.checkout_root));\n        out(io, &format!(\"Target harness folder(s): {}\", targets.join(\", \")));\n        let ans = prompt.ask(io, &format!(\"Link impeccable skills into {} folder(s)? (Y/n) \", targets.len()))?;\n        if ans == \"n\" || ans == \"no\" {\n            out(io, \"Aborted. Re-run with --providers=<names> to choose explicitly (e.g. --providers=claude,cursor).\");\n            return Err(Flow::Exit(0));\n        }\n    }\n    let result = bundle::link_provider_skills(io, &source.bundle_root, &root, &targets, force).map_err(Flow::Throw)?;\n    // Linked installs are excluded from install/update refreshes (overwriting\n    // a symlink would destroy the link), so this is the only path that can\n    // deliver the OpenCode command bridge to them. A copy, not a symlink: the\n    // bridge is static and OpenCode scans the real commands dir. No-ops when\n    // the source checkout has no built commands (#483).","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/skills/src/commands.rs#L451-L487","documentation":"`link` calls `sys.resolve_install_targets` with the `--providers` flag value. If no harness target folders can be determined, the command aborts with exit code 1 and suggests passing providers explicitly.","triggerScenarios":"Running `impeccable link` without `--providers` in an environment where no known harness folder (e.g. `.claude/`, `.cursor/`) exists or is detectable.","commonSituations":"Fresh machines with no provider folders, CI containers, or typos in the providers value resulting in zero matches.","solutions":["Pass providers explicitly: `impeccable link --providers=claude,cursor`","Create the harness folder expected by auto-detection first","Check the providers value for typos"],"exampleFix":"// before\nimpeccable link\n// after\nimpeccable link --providers=claude,cursor","handlingStrategy":"validation","validationCode":"const providers = process.argv.match(/--providers=([\\w,]+)/)?.[1];\nif (!providers) console.error('Pass --providers=claude,cursor explicitly');","typeGuard":null,"tryCatchPattern":"try { await link(); } catch (e) { if (/target harness folder/.test(String(e))) { console.error('Specify --providers'); } }","preventionTips":["Always pass --providers explicitly in scripts and CI","Keep at least one harness folder present for auto-detection"],"tags":["cli","link","providers"],"backgroundTag":"missing-required-flag","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}