{"record":{"id":"9eaafd6a2874c53e","repo":"screenpipe/screenpipe","slug":"skill-name-must-be-lowercase-letters-digits-and","errorCode":null,"errorMessage":"skill name must be lowercase letters, digits, and single hyphens (max 64)","messagePattern":"skill name must be lowercase letters, digits, and single hyphens \\(max 64\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/screenpipe-engine/src/cli/team_skills.rs","lineNumber":375,"sourceCode":"        .ok_or_else(|| anyhow::anyhow!(\"SKILL.md needs a name\"))?\n        .to_string();\n    let description = metadata\n        .get(\"description\")\n        .and_then(serde_yaml::Value::as_str)\n        .map(str::trim)\n        .filter(|value| !value.is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"SKILL.md needs a description\"))?\n        .to_string();\n    let valid_name = !name.is_empty()\n        && name.len() <= 64\n        && !name.starts_with('-')\n        && !name.ends_with('-')\n        && !name.contains(\"--\")\n        && name\n            .chars()\n            .all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '-');\n    if !valid_name {\n        anyhow::bail!(\"skill name must be lowercase letters, digits, and single hyphens (max 64)\");\n    }\n    if description.is_empty() || description.len() > 1024 {\n        anyhow::bail!(\"skill description must contain 1-1024 characters\");\n    }\n    Ok((name, description))\n}\n\nfn print_preview(bundle: &PreparedBundle, title: Option<&str>) {\n    println!(\"team skill proposal preview\");\n    println!(\"title: {}\", title.unwrap_or(&bundle.name));\n    println!(\"name: {}\", bundle.name);\n    println!(\"description: {}\", bundle.description);\n    println!(\"source: {}\", bundle.root.display());\n    println!(\n        \"files: {} · bytes: {} · discovery: {} chars · activated: {} chars · scripts: {}\",\n        bundle.files.len(),\n        bundle.total_bytes,\n        bundle.discovery_chars,","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-engine/src/cli/team_skills.rs#L357-L393","documentation":"`parse_frontmatter` validates the skill `name` from SKILL.md frontmatter. The name must be non-empty, at most 64 bytes, not start or end with '-', contain no consecutive '--', and consist only of ASCII lowercase letters, digits, and single hyphens. Any violation raises this error. This normalization keeps skill names URL/ID-safe and consistent across the team skill registry.","triggerScenarios":"Running the team skill bundle flow with a SKILL.md whose `name:` field uses uppercase letters, spaces, underscores, non-ASCII characters, leading/trailing hyphens, double hyphens, or exceeds 64 characters.","commonSituations":"Naming a skill with CamelCase or spaces (e.g. 'My Skill', 'my_skill'); copying a display title into the name field; migrating older skills that allowed other formats; auto-generated names from paths that contain uppercase or underscores; very long names from concatenated titles.","solutions":["Rewrite the name using only lowercase a-z, 0-9, and single hyphens (no leading/trailing '-', no '--'), max 64 chars","Replace spaces or underscores with single hyphens (e.g. 'my_skill' -> 'my-skill')","Convert uppercase letters to lowercase (e.g. 'MySkill' -> 'myskill')","Shorten names over 64 characters; keep the long title in the description or preview title instead"],"exampleFix":"// before (SKILL.md frontmatter)\nname: My Great_Skill--v2\n// after\nname: my-great-skill-v2","handlingStrategy":"validation","validationCode":"fn is_valid_skill_name(name: &str) -> bool {\n    !name.is_empty()\n        && name.len() <= 64\n        && !name.starts_with('-')\n        && !name.ends_with('-')\n        && !name.contains(\"--\")\n        && name.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')\n}\nassert!(is_valid_skill_name(&name), \"invalid skill name\");","typeGuard":"fn valid_skill_name(name: &str) -> Option<&str> {\n    if !name.is_empty()\n        && name.len() <= 64\n        && !name.starts_with('-')\n        && !name.ends_with('-')\n        && !name.contains(\"--\")\n        && name.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')\n    { Some(name) } else { None }\n}","tryCatchPattern":"match prepare_bundle(&skill_dir) {\n    Err(e) if e.to_string().contains(\"skill name must be\") => {\n        eprintln!(\"use lowercase a-z, 0-9, single hyphens; max 64 chars: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Derive names from folder names and slugify: lowercase, spaces/underscores to single hyphens","Never use display titles verbatim as the name field","Add a name-format lint/regex check (^[a-z0-9]+(-[a-z0-9]+)*$) in CI","Keep names short; put longer descriptions in the description field (1-1024 chars)"],"tags":["yaml","frontmatter","validation","naming"],"backgroundTag":"frontmatter-parse-failed","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}