How Skills Are Discovered Recursively in Superpowers: A Deep Dive into the Filesystem Scanner

Superpowers discovers skills by recursively walking the filesystem up to a depth of three levels, locating every SKILL.md file, and parsing its frontmatter to build a catalog of available capabilities.

The obra/superpowers repository implements a dynamic skill discovery system that eliminates hardcoded lists by scanning directories at runtime. Understanding how skills are discovered recursively in Superpowers is essential for developers extending the agent's capabilities or integrating custom skill repositories.

The Core Discovery Mechanism in lib/skills-core.js

The entire discovery logic resides in lib/skills-core.js, which exports the primary entry point for filesystem traversal and skill metadata extraction.

Recursive Directory Traversal with findSkillsInDir

The findSkillsInDir(dir, sourceType, maxDepth = 3) function initiates a controlled recursive search starting from a specified base directory. The implementation uses an internal recurse helper that iterates over directory entries, descends into subdirectories, and enforces the depth limit to prevent infinite recursion or excessive filesystem traversal.

The default maxDepth of 3 levels provides a balance between discovery thoroughness and performance, ensuring that deeply nested dependency folders or version control directories do not trigger unnecessary scans.

Skill Detection and Frontmatter Parsing

During the recursive walk, every visited directory is checked for the presence of a SKILL.md file. When found, the system invokes extractFrontmatter to parse the YAML frontmatter at the top of the markdown file. This metadata includes the skill's display name, description, and configuration parameters.

The parsing logic validates essential fields and normalizes the data before constructing the skill descriptor, ensuring that malformed skill definitions are handled gracefully without interrupting the discovery process.

The Skill Descriptor Object Structure

Each discovered skill yields a standardized object containing:

  • path – Absolute filesystem path to the skill's containing folder
  • skillFile – Full path to the SKILL.md manifest
  • name – Explicit frontmatter name or fallback to the directory name
  • description – Frontmatter description field (if provided)
  • sourceType – Classification as 'personal' or 'superpowers', indicating the origin repository

The function returns an aggregated array of these descriptors, which serves as the authoritative catalog for the runtime skill selection logic.

Integration Points and Runtime Usage

The recursive discovery system integrates with the broader Superpowers architecture through bootstrap plugins and runtime API calls.

Bootstrap Plugin Initialization

The plugins/superpowers.js bootstrap plugin determines the canonical location of the Superpowers skill directory (resolved as ../../skills relative to the plugin file). During agent initialization, this plugin registers the skill path with the OpenCode environment, preparing the system for dynamic capability loading.

The plugin does not perform the scan itself; rather, it configures the environment so that subsequent calls to the native skill tool can trigger the filesystem walk as needed.

Runtime Skill Catalog Building

When the agent requires knowledge of available capabilities, it invokes skillsCore.findSkillsInDir(superpowersDir, 'superpowers') for bundled skills, or the equivalent call with 'personal' for user-defined extensions. The returned catalog drives the skill-selection logic that determines which capability to invoke based on the current task context.

This deferred discovery pattern ensures that skill manifests are loaded fresh for each session, accommodating changes to the filesystem without requiring agent restarts or code modifications.

Practical Code Examples

Directly Invoking the Discovery Function

import * as skillsCore from './lib/skills-core.js';
import path from 'path';

// Absolute path to the bundled Superpowers skills folder
const superpowersDir = path.resolve(import.meta.url, '../../skills');

// Discover all Superpowers-provided skills (recursively, up to depth 3)
const allSuperpowers = skillsCore.findSkillsInDir(superpowersDir, 'superpowers');

console.log('Found', allSuperpowers.length, 'Superpowers skills:');
allSuperpowers.forEach(s => console.log(`- ${s.name} (${s.path})`));

This returns an array of skill objects representing capabilities such as brainstorming, writing-plans, and others defined in the repository.

Merging Personal and Superpowers Skill Sets

import * as skillsCore from './lib/skills-core.js';
import path from 'path';

const superpowersDir = path.resolve('../../skills');
const personalDir = path.resolve('~/.config/opencode/skills/personal');

const superSkills = skillsCore.findSkillsInDir(superpowersDir, 'superpowers');
const personalSkills = skillsCore.findSkillsInDir(personalDir, 'personal');

// Personal skills shadow Superpowers ones if names clash
const merged = [...personalSkills];
for (const sp of superSkills) {
  if (!merged.find(s => s.name === sp.name)) merged.push(sp);
}

This pattern allows users to override bundled capabilities with custom implementations while maintaining the recursive discovery mechanism for both sources.

Using the OpenCode Skill Tool Wrapper

// Inside an OpenCode agent script
const skills = await skill('list-skills', {
  directory: '/home/user/.config/opencode/skills',
  source: 'superpowers'   // or 'personal'
});
console.log('Available skills:', skills.map(s => s.name));

The underlying implementation of skill('list-skills') delegates directly to findSkillsInDir, providing a high-level API over the recursive filesystem scanner.

Summary

  • Superpowers discovers skills recursively by walking the filesystem from a configurable root directory, defaulting to a maximum depth of three levels to balance thoroughness with performance.
  • The core logic resides in lib/skills-core.js, specifically within the findSkillsInDir function, which uses an internal recurse helper to traverse directories and identify SKILL.md manifest files.
  • Each discovered skill yields a standardized descriptor object containing the absolute path, manifest location, name, description, and source type, enabling the runtime to build a unified catalog of capabilities.
  • Integration occurs through plugins/superpowers.js, which configures the skill directory path, and through runtime calls to the discovery function that enable dynamic skill loading without hardcoded lists.

Frequently Asked Questions

How does Superpowers prevent infinite recursion when scanning for skills?

The findSkillsInDir function enforces a default maxDepth parameter of 3, which limits how many directory levels the recursive walker descends. The internal recurse helper checks the current depth against this limit before entering subdirectories, ensuring the scanner stops at a reasonable boundary even if the filesystem contains deeply nested structures.

What file does Superpowers look for to identify a valid skill directory?

Superpowers searches for a file named exactly SKILL.md in every directory visited during the recursive walk. When this file is found, the system parses its YAML frontmatter using the extractFrontmatter function to extract metadata such as the skill name and description. Directories without a SKILL.md file are skipped and not included in the final skill catalog.

Can I override the default depth limit for skill discovery?

Yes, the findSkillsInDir function accepts an optional third parameter maxDepth that defaults to 3. You can pass a higher or lower integer to adjust the search depth according to your directory structure. For example, calling skillsCore.findSkillsInDir(dir, 'personal', 5) would scan five levels deep instead of the default three, useful if your skills are organized in a deeply nested taxonomy.

Where does the recursive skill scanner integrate with the OpenCode runtime?

The discovery mechanism integrates through the plugins/superpowers.js bootstrap module, which resolves the path to the bundled skills directory (../../skills) and makes it available to the agent. At runtime, when the agent needs to enumerate capabilities, it invokes skillsCore.findSkillsInDir with the configured directory and a sourceType of 'superpowers' or 'personal'. This deferred execution pattern ensures the filesystem scan occurs fresh for each session, reflecting any changes to skill definitions without requiring a restart.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →