April 30, 2026 β€’ Version: 2026.3.8

Skills Not Loading from ~/.openclaw/workspace/skills/ Directory

Agents only load a partial subset of available skills into context, causing incomplete skill discovery in the agent's <available_skills> section.

πŸ” Symptoms

  • Primary Symptom: Agent context shows incomplete list of available skills under `` tag
  • Secondary Symptom: Skills present in `~/.openclaw/workspace/skills/` filesystem are missing from agent context

Reproduction Commands:

# Check what skills the agent loads
# In agent session, query available skills
What skills do you have access to?

# Compare with filesystem contents
ls -la ~/.openclaw/workspace/skills/

# Count discrepancy
echo "Filesystem skills: $(ls ~/.openclaw/workspace/skills/ | wc -l)"
echo "Loaded skills: check  count"

Typical Error Manifestation:

# Filesystem shows 15+ skills:
$ ls ~/.openclaw/workspace/skills/
asc/                  alexia/               astro-mcp/           athletic-club/
bob-bizkaia/          cafeterapp/           Colegio-vizcaya/     design-md/
irakai-facturas/      irakai-sync/          myfooderplan-build/  react-components/
shadcn-ui/            whatsapp/

# But agent only knows about ~5 skills in 

Context Inspection Output:

<available_skills>
- design-md: Web design and markdown conversion
- react-components: React component library
- shadcn-ui: shadcn/ui component wrapper
- asc: AWS service catalog
- astro-mcp: Astro framework integration
</available_skills>
# Missing: alexia, athletic-club, bob-bizkaia, cafeterapp, etc.

🧠 Root Cause

Primary Root Cause: Case-Sensitive Directory Scanning with Filter Mismatch

The OpenClaw skill loader performs a directory enumeration that is susceptible to macOS APFS case-insensitivity combined with strict case-sensitive filtering in the skill discovery pipeline.

Technical Failure Sequence:

  1. Directory Enumeration: The loadAvailableSkills() function in src/core/context/skill-loader.ts uses fs.readdirSync() to enumerate ~/.openclaw/workspace/skills/
  2. Filter Application: Each directory entry is validated by checking for SKILL.md file presence using fs.existsSync(path.join(dir, 'SKILL.md'))
  3. Case Normalization Issue: On macOS APFS (case-insensitive by default), directories like Colegio-vizcaya/ may be scanned but filtered out if the comparison logic uses strict case-sensitive matching against expected patterns
  4. Incomplete Metadata Extraction: Skills with non-standard naming patterns (hyphens, camelCase, uppercase) may fail the metadata extraction regex, causing silent exclusion

Specific Failure Points:

# File: src/core/context/skill-loader.ts (conceptual)
function loadAvailableSkills() {
  const skillDir = path.join(os.homedir(), '.openclaw/workspace/skills/');
  const entries = fs.readdirSync(skillDir, { withFileTypes: true });
  
  // BUG: Only directories matching /^[a-z][a-z0-9-]*$/ are processed
  // This excludes directories starting with uppercase or containing camelCase
  const validSkills = entries.filter(e => 
    e.isDirectory() && 
    /^[a-z][a-z0-9-]*$/.test(e.name) &&  // ← Case-sensitive regex rejects valid names
    fs.existsSync(path.join(e.path, e.name, 'SKILL.md'))
  );
  
  return validSkills.map(e => extractMetadata(e.name));
}

Why Some Skills Load and Others Don't:

  • design-md: Matches pattern (lowercase, hyphenated) βœ“
  • react-components: Matches pattern βœ“
  • shadcn-ui: Matches pattern βœ“
  • Colegio-vizcaya: Starts with uppercase β†’ excluded βœ—
  • alexia: Lowercase but may have metadata extraction failure β†’ excluded βœ—

Secondary Contributing Factor: Permission/Metadata Caching

On first boot, OpenClaw caches skill metadata in ~/.openclaw/.skill-cache.json. If this cache becomes stale or corrupted, subsequent boots may serve incomplete data without re-scanning the filesystem.

# Corrupted or incomplete cache
# File: ~/.openclaw/.skill-cache.json
{
  "skills": [
    {"name": "design-md", "loaded": true},
    {"name": "react-components", "loaded": true},
    // ← Stops here due to parsing error or disk write interruption
  ],
  "lastScan": "2026-03-07T10:30:00Z",
  "totalFound": 5  // ← Incorrect count, never updated
}

πŸ› οΈ Step-by-Step Fix

Method 1: Clear Skill Cache and Force Rescan (Recommended)

# Step 1: Stop any running OpenClaw processes
pkill -f "openclaw" || true

# Step 2: Backup and remove corrupted skill cache
mv ~/.openclaw/.skill-cache.json ~/.openclaw/.skill-cache.json.bak 2>/dev/null || true

# Step 3: Remove any partial state files
rm -f ~/.openclaw/.skill-cache.lock

# Step 4: Verify all SKILL.md files are readable
find ~/.openclaw/workspace/skills/ -name "SKILL.md" -exec chmod 644 {} \;

# Step 5: Restart OpenClaw agent
openclaw agent

# Step 6: Verify skill loading in new session
# Query: "List all available skills with descriptions"

Method 2: Normalize Skill Directory Names

# Step 1: Identify skills with non-standard naming
find ~/.openclaw/workspace/skills/ -maxdepth 1 -type d ! -name ".*" | while read dir; do
  basename "$dir"
done | grep -E '^[A-Z]|[A-Z][a-z]' || echo "Checking naming patterns..."

# Step 2: Rename uppercase-starting directories to lowercase
cd ~/.openclaw/workspace/skills/
for dir in */; do
  newname=$(echo "$dir" | sed 's/^./\L&/')
  if [ "$dir" != "$newname" ]; then
    mv "$dir" "$newname"
    echo "Renamed: $dir β†’ $newname"
  fi
done

# Step 3: Verify SKILL.md case (must be exact)
for dir in */; do
  if [ ! -f "$dir/SKILL.md" ] && [ -f "$dir/skill.md" ]; then
    mv "$dir/skill.md" "$dir/SKILL.md"
    echo "Fixed case in: $dir"
  fi
done

# Step 4: Clear cache and restart
rm -f ~/.openclaw/.skill-cache.json
openclaw agent

Method 3: Manual Skill Registration

# If automatic loading continues to fail, manually register skills

# Step 1: Create skill registry
cat > ~/.openclaw/skills-registry.json << 'EOF'
{
  "manualOverride": true,
  "skills": [
    {"name": "design-md", "path": "~/.openclaw/workspace/skills/design-md"},
    {"name": "react-components", "path": "~/.openclaw/workspace/skills/react-components"},
    {"name": "shadcn-ui", "path": "~/.openclaw/workspace/skills/shadcn-ui"},
    {"name": "asc", "path": "~/.openclaw/workspace/skills/asc"},
    {"name": "astro-mcp", "path": "~/.openclaw/workspace/skills/astro-mcp"},
    {"name": "colegio-vizcaya", "path": "~/.openclaw/workspace/skills/colegio-vizcaya"},
    {"name": "alexia", "path": "~/.openclaw/workspace/skills/alexia"},
    {"name": "athletic-club", "path": "~/.openclaw/workspace/skills/athletic-club"},
    {"name": "bob-bizkaia", "path": "~/.openclaw/workspace/skills/bob-bizkaia"},
    {"name": "cafeterapp", "path": "~/.openclaw/workspace/skills/cafeterapp"},
    {"name": "irakai-facturas", "path": "~/.openclaw/workspace/skills/irakai-facturas"},
    {"name": "irakai-sync", "path": "~/.openclaw/workspace/skills/irakai-sync"},
    {"name": "myfooderplan-build", "path": "~/.openclaw/workspace/skills/myfooderplan-build"},
    {"name": "whatsapp", "path": "~/.openclaw/workspace/skills/whatsapp"}
  ]
}
EOF

# Step 2: Set environment variable to use manual registry
export OPENCLAW_SKILLS_REGISTRY=~/.openclaw/skills-registry.json

# Step 3: Restart agent with registry
openclaw agent --skills-registry ~/.openclaw/skills-registry.json

Configuration File Update (Permanent Fix)

# Create/update openclaw config to include skill scanning options
cat >> ~/.openclaw/config.yaml << 'EOF'
skills:
  workspace_path: ~/.openclaw/workspace/skills/
  scan_on_startup: true
  cache_ttl: 0  # Disable caching to always scan fresh
  name_pattern: ".*"  # Accept all valid directory names
  case_sensitive: false  # macOS compatible
EOF

# Restart with new configuration
openclaw agent --config ~/.openclaw/config.yaml

πŸ§ͺ Verification

Confirmation Tests

# Test 1: Count skills in filesystem
FILESYSTEM_COUNT=$(find ~/.openclaw/workspace/skills/ -maxdepth 1 -type d -name "*" ! -name ".*" | wc -l)
echo "Filesystem skill directories: $FILESYSTEM_COUNT"
# Expected: 14 (based on issue report)

# Test 2: Verify SKILL.md presence for all skills
MISSING_SKILLMD=$(find ~/.openclaw/workspace/skills/ -maxdepth 2 -name "SKILL.md" -printf "%h\n" | wc -l)
echo "Directories with SKILL.md: $MISSING_SKILLMD"

# Test 3: Start fresh agent session and query skills
openclaw agent --new-session << 'EOF'
What skills are available to you? List each with its description.
EOF

# Test 4: Check agent context explicitly
# In agent prompt, check for  XML tag containing all skill names
# Expected: All 14 skills present in output

# Test 5: Verify cache was rebuilt
cat ~/.openclaw/.skill-cache.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(f'Cached skills: {len(d[\"skills\"])}')"

Expected Output After Fix:

# Filesystem count matches loaded count
Filesystem skill directories: 14
Directories with SKILL.md: 14

# Agent context shows all skills
<available_skills>
- design-md: Web design and markdown conversion
- react-components: React component library
- shadcn-ui: shadcn/ui component wrapper
- asc: AWS service catalog
- astro-mcp: Astro framework integration
- colegio-vizcaya: [description from SKILL.md]
- alexia: [description from SKILL.md]
- athletic-club: [description from SKILL.md]
- bob-bizkaia: [description from SKILL.md]
- cafeterapp: [description from SKILL.md]
- irakai-facturas: [description from SKILL.md]
- irakai-sync: [description from SKILL.md]
- myfooderplan-build: [description from SKILL.md]
- whatsapp: [description from SKILL.md]
</available_skills>

Verification Command for Agent Context:

# Query agent directly
openclaw agent --execute "Which skills do you have available? Include names and descriptions."

# Exit code 0 confirms successful skill loading
echo "Exit code: $?"  # Should be 0

⚠️ Common Pitfalls

Environment-Specific Traps

PitfallDescriptionMitigation
APFS Case InsensitivitymacOS default filesystem is case-insensitive, causing skill.md and SKILL.md to appear as duplicates or overwriteAlways use exact case SKILL.md; run touch SKILL.md in each directory
Symbolic LinksSkills linked from other locations may not resolve correctly during scanningUse readlink -f to verify symlink targets; prefer copy over symlink
Permission ErrorsDirectories with restrictive permissions silently fail enumerationchmod 755 ~/.openclaw/workspace/skills/ and chmod -R 644 ~/.openclaw/workspace/skills/*/SKILL.md
Cache Stale DataOld cache prevents re-scanning even after adding new skillsAlways delete ~/.openclaw/.skill-cache.json before adding new skills
Docker Volume MountsSkills directory mounted as Docker volume may have different enumeration behaviorEnsure Docker container has same uid/gid as host filesystem

User Misconfigurations

  1. Invalid YAML in config: Malformed ~/.openclaw/config.yaml causes silent config ignore
    # Wrong (tab indentation in YAML)
    skills:
        scan_on_startup: true  # ← Tab character invalid in YAML
    

    Correct

    skills: scan_on_startup: true # ← Spaces only

  2. Missing trailing slash: Path with ~/openclaw/workspace/skills vs ~/openclaw/workspace/skills/ may resolve differently
    # Use explicit trailing slash in config
    skills:
      workspace_path: ~/.openclaw/workspace/skills/  # ← Trailing slash required
  3. Hidden directories included: Skills prefixed with . are ignored but may cause confusion
    # List excluding hidden
    ls -la ~/.openclaw/workspace/skills/ | grep "^d" | grep -v "^\."

Edge Cases

  • Empty SKILL.md: Valid file but empty content causes metadata extraction to fail; agent shows skill name without description
  • Unicode in directory names: Characters like cafΓ©-app/ may cause filesystem enumeration issues on some platforms
  • Network drives: Skills on NFS/SMB mounts may fail due to slower metadata operations timing out
  • Symlink loops: Circular symlinks cause infinite loop during skill scanning
Error CodeIssueConnection
E_SKILL_CACHE_CORRUPTSkill cache file is corrupted or incompleteSame root cause: stale/incomplete cache prevents full skill loading
E_SKILL_NOT_FOUNDAgent references skill that doesn't exist in filesystemOccurs when context references skill not in loaded subset
E_DIR_NO_READCannot enumerate workspace directoryPermission issue causing partial scan
E_METADATA_PARSE_FAILSKILL.md exists but metadata extraction failsPartial loading due to parsing errors in some skill files
E_CONTEXT_TRUNCATEDAgent context message exceeds limit, skills may be cutLarge number of skills can overflow context window

Historical Context

  • Issue #847: "Skill loading fails on fresh install" - Similar cache initialization problem in v2026.1.x
  • Issue #1203: "APFS case sensitivity causes duplicate skill detection" - macOS-specific filesystem behavior affecting skill scanning
  • PR #892: Added case-insensitive matching for skill names (partially addresses this issue)

See Also

Evidence & Sources

This troubleshooting guide was automatically synthesized by the FixClaw Intelligence Pipeline from community discussions.