DESIGN.md@docs · diff
git:20260708.1981225 to git:20260709.7e7110d
1 added, 1 removed. Audit A to A.
# Technical Design: Skill Triggering, Routing, and Loading
How superpowers-plus discovers skills, matches them to user intent, loads them, and compresses them for token efficiency. This document covers internal mechanisms. For pipeline topology (which skills call which), see [SKILL_TAXONOMY.md](SKILL_TAXONOMY.md). For dependency graphs, see [skill-dependency-graph.md](skill-dependency-graph.md). For deployment paths, see [ARCHITECTURE.md](ARCHITECTURE.md).
---
## Contents
1. [Frontmatter Schema](#1-frontmatter-schema)
2. [Trigger Mechanisms](#2-trigger-mechanisms)
3. [Semantic Skill Router](#3-semantic-skill-router)
4. [Skill Loading Pipeline](#4-skill-loading-pipeline)
5. [Compression Pipeline](#5-compression-pipeline)
6. [Coordination Resolution](#6-coordination-resolution)
7. [Composition and Capability Pipeline](#7-composition-and-capability-pipeline)
8. [Bootstrap Flow](#8-bootstrap-flow)
9. [Namespace Resolution](#9-namespace-resolution)
---
## 1. Frontmatter Schema
Every `skill.md` begins with a YAML frontmatter block. The canonical parser is [`lib/frontmatter.js`](../lib/frontmatter.js). Validation runs at discovery time via `validateFrontmatter()`.
```yaml
---
name: skill-name # string, REQUIRED — must match directory name
source: superpowers-plus # string, REQUIRED — owning repo identifier
description: "One-line skill description" # string, REQUIRED — used in skill discovery index
triggers: ["phrase one", "phrase two"] # string[], optional — makes this a superpower (auto-invoked)
anti_triggers: ["phrase to suppress"] # string[], optional — suppress activation on match
aliases: ["alt-name"] # string[], optional — alternate lookup names
- overrides: superpowers/skill-name # string, optional — declares upstream skill being replaced
+ overrides: source-name/skill-name # string, optional — overlay drift/dup suppression only (see tools/doctor-modules/); the `superpowers/...` source name is retired as of v2.6.0, deploy.sh warns and asks you to remove it
summary: "Short summary for probe mode" # string, optional — shown by use-skill --probe
augment_menu: false # boolean, optional, default false — true exports skill to ~/.agents/skills/ slash menu
compress: true # boolean, optional, default true — set false to skip compression
requires_mcp: ["server-name"] # string[], optional — MCP servers that must be registered
mcp_install_hint: "path/to/install.sh" # string, optional — shown when requires_mcp not met
coordination: # object, optional — DAG metadata (see §6)
group: domain-name # string — logical grouping for graph rendering
order: 1 # integer — tie-break in topological sort (ascending)
requires: ["skill-a"] # string[] — blocking prerequisites
enables: ["skill-b"] # string[] — downstream skills this unlocks
escalates_to: ["skill-c"] # string[] — fallback if this skill is insufficient
internal: false # boolean — if true, hidden from user-facing lists
composition: # object, optional — capability/artifact metadata (see §7)
produces: ["artifact-name"] # string[] — named outputs this skill emits
consumes: ["artifact-name"] # string[] — named inputs this skill requires
capabilities: ["capability-name"] # string[] — named capabilities this skill provides
priority: 50 # integer, default 50 — execution order (ascending)
optional: false # boolean — whether this skill can be skipped
requires_all: false # boolean — whether all consumes must be satisfied
---
```
### Field Classification
| Field | Required | Type | Default | Purpose |
|-------|----------|------|---------|---------|
| `name` | Yes | string | — | Skill identifier |
| `source` | Yes | string | — | Owning repository |
| `description` | Yes | string | — | One-line discovery text |
| `triggers` | No | string[] | `[]` | Auto-invocation phrases → makes skill a **superpower** |
| `anti_triggers` | No | string[] | `[]` | Suppression phrases — prevent false activations |
| `aliases` | No | string[] | `[]` | Alternate lookup names |
| `overrides` | No | string | — | Declares upstream skill being replaced |
| `summary` | No | string | — | Short description for `--probe` mode |
| `augment_menu` | No | boolean | `false` | Set `true` to export this skill to `~/.agents/skills/` (Augment IDE slash menu). Command name is the first `/sp*` trigger; falls back to the skill directory name |
| `compress` | No | boolean | `true` | Set `false` to skip compression |
| `requires_mcp` | No | string[] | `[]` | Required MCP server names |
| `mcp_install_hint` | No | string | — | Install script shown when MCP is missing |
| `coordination` | No | object | `null` | DAG metadata for chain resolution |
| `coordination.group` | No | string | — | Logical group label |
| `coordination.order` | No | integer | `0` | Topo-sort tie-break (ascending) |
| `coordination.requires` | No | string[] | `[]` | Blocking prerequisites |
| `coordination.enables` | No | string[] | `[]` | Downstream skills |
| `coordination.escalates_to` | No | string[] | `[]` | Fallback targets |
| `coordination.internal` | No | boolean | `false` | Hidden from user-facing lists |
| `composition` | No | object | `null` | Capability/artifact metadata |
| `composition.produces` | No | string[] | `[]` | Named outputs |
| `composition.consumes` | No | string[] | `[]` | Required inputs |
| `composition.capabilities` | No | string[] | `[]` | Named capabilities provided |
| `composition.priority` | No | integer | `50` | Execution priority (ascending) |
| `composition.optional` | No | boolean | `false` | Skill may be skipped |
| `composition.requires_all` | No | boolean | `false` | All `consumes` must be satisfied |
---
## 2. Trigger Mechanisms
There are two separate systems that use `triggers` and `anti_triggers`:
### 2a. AI-Native Trigger Matching (Primary)
The primary trigger mechanism is **semantic matching by the LLM itself**. At session start, `bootstrap` emits a compact skill index. The AI reads each skill's `triggers` list and decides contextually when to invoke a skill — no string matching code is involved. On Claude Code, skill invocation uses the native Skill tool rather than a CLI call; the index delivery and decision logic are otherwise identical.
```mermaid
sequenceDiagram
participant User
participant AI as LLM (Claude / Augment)
participant Bootstrap as superpowers-augment bootstrap
participant Index as Skill Index (~/.codex/.skill-index.json)
Note over AI,Bootstrap: Session Start
AI->>Bootstrap: run bootstrap
Bootstrap->>Index: findAllSkills() → scan personal + superpowers dirs
Bootstrap-->>AI: skill index (name, description, triggers, isSuperpower)
Note over AI: Index is injected into system context
Note over User,AI: User sends a message
User->>AI: "help me brainstorm a feature"
AI->>AI: Compare query to all triggers[] in index
Note over AI: "brainstorm" matches brainstorming.triggers
AI->>AI: anti_triggers check — reject if match
Note over AI: no anti_triggers match → proceed
AI->>Bootstrap: use-skill brainstorming
Bootstrap-->>AI: compressed skill content
AI->>User: executes skill procedure
```
The AI applies **intent-based inference**: it evaluates the *full conversational context*, not just substring matching. This is why `anti_triggers` is needed — without it, broad trigger phrases fire on unrelated queries.
**Example — brainstorming `anti_triggers` preventing false activation:**
```yaml
triggers: ["brainstorm", "design a feature", "build a new"]
anti_triggers: ["radical improvement", "10x improvement", "comparing design options"]
```
Without `anti_triggers`, "compare design options" would incorrectly fire `brainstorming` instead of `debate`.
### 2b. Semantic Skill Router (CLI / Programmatic)
The `match-skills` command uses [`lib/skill-router.js`](../lib/skill-router.js) for programmatic skill lookup. This uses code-side matching and is the basis for tooling integration. See §3 for the full algorithm.
```bash
node ~/.codex/superpowers-augment/superpowers-augment.js match-skills "my tests keep failing"
```
---
## 3. Semantic Skill Router
Used by `match-skills` command and optional tooling integrations. Implements hybrid **TF-IDF + Intent Pattern** matching with heuristic boosts. Source: [`lib/skill-router.js`](../lib/skill-router.js) and [`lib/intent-patterns.js`](../lib/intent-patterns.js).
### Scoring Pipeline
```mermaid
flowchart TD
Q[User query string]
Q --> TOK[tokenize + stem<br/>remove stop words]
TOK --> EXP[expand via CONCEPT_EXPANSIONS<br/>e.g. stuck → think-twice debug]
EXP --> TFIDF[TF-IDF cosine similarity<br/>against name + description + triggers]
TFIDF --> BASE[base score per skill]
BASE --> IP{Intent pattern<br/>match?}
IP -->|yes| IPB[+1.5 to +8 boost<br/>from INTENT_PATTERNS]
IP -->|no| ENXT[continue]
IPB --> ENXT
ENXT --> NM{Exact name<br/>match?}
NM -->|yes| NMB[+0.5 boost]
NM -->|no| TM
NMB --> TM{Trigger phrase<br/>match?}
TM -->|full match| TMF[+1.2 boost]
TM -->|partial match| TMP[+0.6 × coverage]
TM -->|no match| AT
TMF --> AT
TMP --> AT
AT{Anti-trigger<br/>match?}
AT -->|yes| ATP[-2.0 penalty]
AT -->|no| WM
ATP --> WM{Name word<br/>match > 3 chars?}
WM -->|yes| WMB[+0.3 per word]
WM -->|no| DM
WMB --> DM{Description<br/>keyword match?}
DM -->|yes| DMB[+0.2 per raw term]
DM -->|no| SORT
DMB --> SORT
SORT[Sort by final score<br/>Return top-N results]
```
### TF-IDF Index Construction
Each skill's index text is: `name (spaces) + name (kebab) + description + triggers.join(' ')`.
Terms are stemmed (suffix removal: `-ing`, `-ed`, `-s`, `-ly`, `-tion→t`, `-ment`) and stop-words filtered before TF-IDF vectorization.
### Intent Pattern Boosts
[`lib/intent-patterns.js`](../lib/intent-patterns.js) defines high-confidence phrase → skill mappings with non-linear boost levels:
| Boost Level | Value | When to Use |
|-------------|-------|-------------|
| `BOOST_DEFAULT` | 1.5 | Weak signal, no boost specified |
| `BOOST_LOW` | 2 | Generic code-change intent |
| `BOOST_STANDARD` | 3 | Domain-specific intent clearly maps to a skill |
| `BOOST_ELEVATED` | 4 | Multi-step workflow skills |
| `BOOST_HIGH` | 5 | Code review variants |
| `BOOST_CRITICAL` | 6 | Active reviewer protocol |
| `BOOST_EMERGENCY` | 8 | Failure autopsy, explicit disaster |
Boosts accumulate across matched patterns. A single query can receive boosts from multiple patterns.
### Query Expansion
`CONCEPT_EXPANSIONS` maps stemmed terms to related domain terms before TF-IDF scoring:
```
stuck → think-twice, help, research, perplexity
bug → systematic-debugging, fix, error, fail
wiki → edit, author, document, orchestrate
commit → git, pre-commit, push, gate
```
### Embedding Mode (Optional)
When `OPENAI_API_KEY` is set, `--embedding` flag switches to OpenAI `text-embedding-3-small` for vector similarity. Embeddings are cached in `~/.codex/.skill-embeddings.json` keyed by content hash. Heuristic boosts (intent patterns, trigger matches, anti-trigger penalties) are applied on top of the embedding score in both modes.
---
## 4. Skill Loading Pipeline
The `use-skill <name>` command executes this pipeline. Source: [`superpowers-augment.js`](../superpowers-augment.js) `useSkill()`.
```mermaid
sequenceDiagram
participant CLI as CLI caller
participant SA as superpowers-augment.js
participant NS as resolveSkillNamespace()
participant FS as Filesystem
participant FM as lib/frontmatter.js
participant MCP as MCP check
participant CMP as lib/compress.js
participant TFM as transformOutput()
CLI->>SA: use-skill <skill-name>
SA->>SA: checkBootstrap() — warn if not bootstrapped
SA->>NS: resolveSkillNamespace(skillName)
NS->>NS: parse namespace prefix (superpowers:, spp:, spo:)
NS->>NS: apply dash shorthand (sp-X → superpowers-X)
NS->>FS: scan personal dir → superpowers dir → alias fallback
NS-->>SA: { skillFile, actualName }
alt skill not found
SA-->>CLI: error + similarity suggestions
end
alt --probe flag
SA->>FS: read file for size + frontmatter only
SA-->>CLI: summary + token cost estimate
end
SA->>FS: readFileSync(skillFile)
SA->>FM: extractFrontmatter(skillFile)
FM-->>SA: { triggers, anti_triggers, compress, requires_mcp, ... }
SA->>MCP: checkMcpPrerequisites(requires_mcp)
alt MCP missing
SA-->>CLI: ⚠️ missing MCP warning (non-blocking)
end
SA->>FM: stripFrontmatter(content)
FM-->>SA: body (no YAML block)
alt compress === false
SA->>SA: skip compression
else
SA->>CMP: compressSkillContent(body)
CMP-->>SA: compressed body (20–40% reduction)
end
SA->>TFM: transformOutput(compressed)
Note over TFM: Rewrites tool names for platform<br/>(e.g. Read→view, Edit→str-replace-editor)
TFM-->>SA: platform-adapted content
SA->>SA: workflowState.recordSkillInvocation(actualName)
SA-->>CLI: "# Skill: <name>\n" + content
```
### Probe Mode
`use-skill --probe <name>` reads only the frontmatter and file size, printing a cost estimate without loading the full content. Shows `summary:` if present, falls back to `description:`.
### Platform Transformation
`transformOutput()` rewrites tool names for the target platform via `TOOL_MAPPINGS` regex substitutions. This allows skill content to use Claude Code tool names (`Read`, `Edit`, `Bash`, `Skill`) while Augment Code receives its equivalents (`view`, `str-replace-editor`, `launch-process`, `superpowers-augment use-skill`).
---
## 5. Compression Pipeline
Source: [`lib/compress.js`](../lib/compress.js). Applied to all skill bodies by default. Opt out with `compress: false` frontmatter. Typical reduction: 20–40%.
```mermaid
flowchart TD
IN[Raw skill body<br/>frontmatter already stripped]
IN --> DOT[Step 0a: Remove fenced dot code blocks<br/>before code-block protection, so they are deleted rather than preserved]
DOT --> PROTECT[Step 0b: Protect remaining code blocks<br/>from EXTREMELY_IMPORTANT extraction]
PROTECT --> EX[Step 1a: Extract EXTREMELY_IMPORTANT blocks<br/>before any section stripping]
EX --> STRIP[Step 1b: Strip boilerplate sections by heading<br/>STRIP_SECTIONS patterns]
STRIP --> RESTORE[Step 1c: Restore extracted blocks<br/>Append under 'Critical Rules' if their parent was stripped]
RESTORE --> UNPROTECT[Restore the code blocks protected in Step 0b]
UNPROTECT --> HTML[Strip frontmatter markers, horizontal rules, and HTML comments]
HTML --> D2[Phase 2: Density reductions<br/>applied OUTSIDE code blocks only]
D2 --> NAV[Strip Wrong-skill navigation blockquotes]
NAV --> ANN[Strip Announce-at-start lines]
ANN --> HEAD[Normalize heading markup<br/>remove bold/italic from headings]
HEAD --> WS[Collapse excess whitespace<br/>trim trailing spaces]
WS --> OUT[Compressed skill body]
```
### Sections Stripped (Phase 1 — `STRIP_SECTIONS`)
These headings and their content are removed as boilerplate — they aid human navigation but not agent execution:
`When to Use`, `Overview`, `Common Rationalizations`, `Why Order/This/It/the Gate Matters/Exists`, `Quick Reference`, `Related Skills`, `Cross-References`, `Integration with *`, `Reference Files`, `When This Skill Fires`, `When NOT to Use`, `Manual Invocation`, `I'm Stuck`, `Companion Skills`, `Escalation Path`, `Example`, `Example Invocation`, `Example:*`, `Rationalizations to Reject`, `Anti-Patterns`, `Purpose`, `Success Criteria`, `Stop Conditions`, `Escalation Conditions`, `When to Invoke`, `WHEN TO USE THIS SKILL`, `Trigger Conditions`
### Content Preserved Unconditionally
| Content | Why |
|---------|-----|
| `<EXTREMELY_IMPORTANT>` blocks | Operative safety gates (extracted pre-strip, restored post-strip) |
| `Failure Modes` sections | Runtime error handling — agent needs this |
| `Incident Log / Record / History` | Recurrence-prevention context — real past failures |
| `References` sections | Pointers to reference files (distinct from `Reference Files`) |
| `Hallucination Prevention` sections | URL fabrication prevention rules |
| Code blocks | Procedural content |
| Tables | Structured data |
| Checklists | Procedural steps |
> **Incident 2026-04-14:** `STRIP_SECTIONS` previously included `Hallucination Prevention`, `References`, and `Incident Log`. This deleted URL verification rules from `link-verification` and `issue-link-verification`, causing wiki authoring to produce broken hyperlinks. All three were removed from `STRIP_SECTIONS`. The `<EXTREMELY_IMPORTANT>` pre-extraction mechanism was added as a safety net. See [ARCHITECTURE.md § Incident 2026-04-14](ARCHITECTURE.md#incident-2026-04-14) for the operational record.
---
## 6. Coordination Resolution
The `coordination:` frontmatter block defines how skills relate to each other in execution chains. Source: [`lib/skill-router.js`](../lib/skill-router.js) `resolveCoordinationChain()` and `getEscalationTargets()`.
### Edge Types
| Field | Direction | Blocking? | Description |
|-------|-----------|-----------|-------------|
| `requires` | incoming | Yes | This skill needs the named skill to run first |
| `enables` | outgoing | No (warn) | This skill unlocks the named skill next |
| `escalates_to` | outgoing | No | If insufficient, escalate to named skill |
`A.enables = [B]` and `B.requires = [A]` produce the **same edge** (`A → B`). They are not additive.
### Chain Resolution (Kahn's Algorithm)
```mermaid
sequenceDiagram
participant Caller
participant CR as resolveCoordinationChain()
participant Graph as Edge Graph
Caller->>CR: resolveCoordinationChain("brainstorming", allSkills)
CR->>CR: build skillMap from coordination metadata
CR->>Graph: normalize edges<br/>A.enables=[B] → A→B<br/>B.requires=[A] → A→B (same)
CR->>CR: check requires[] for missing skills
alt required skill not installed
CR-->>Caller: error: MISSING_REQUIRED_SKILL
end
CR->>CR: collectPredecessors(start) — walk requires[] back
CR->>CR: collectSuccessors(start) — walk enables[] forward
CR->>CR: Kahn topological sort over reachable subgraph<br/>tie-break: coordination.order ASC, then alpha
alt cycle detected
CR-->>Caller: error: CYCLE_DETECTED<br/>names of skills in cycle
end
CR-->>Caller: { chain: ["skill-a", "brainstorming", "debate"], explanation: [...] }
```
### Escalation Resolution
`escalates_to` is checked separately from the chain. When a skill signals it is insufficient (e.g., `think-twice` cannot resolve the problem), the caller checks `getEscalationTargets()` and invokes the fallback:
```mermaid
flowchart LR
TWT[think-twice] ==>|escalates_to| PR[perplexity-research]
SD[systematic-debugging] ==>|escalates_to| TO[thinking-orchestrator]
BL[blast-radius-check] ==>|escalates_to| UCG[unified-commit-gate]
```
For the full escalation map across all skills, see [skill-dependency-graph.md](skill-dependency-graph.md).
---
## 7. Composition and Capability Pipeline
The `composition:` frontmatter block defines skills in terms of **artifacts** they produce/consume and **capabilities** they provide. Source: [`lib/skill-router.js`](../lib/skill-router.js) `buildPipeline()`, `getComposition()`.
### Artifact Flow
```mermaid
sequenceDiagram
participant Caller
participant BP as buildPipeline()
participant FC as findSkillWithCapability()
participant FP as findProducers()
Caller->>BP: buildPipeline("publishes-wiki", allSkills)
BP->>FC: find skill with capability "publishes-wiki"
FC-->>BP: wiki-orchestrator
BP->>BP: resolve wiki-orchestrator.consumes
loop for each consumed artifact
BP->>FP: findProducers(artifact, allSkills)
FP-->>BP: skills that produce this artifact<br/>sorted by composition.priority ASC
BP->>BP: recursively resolve their consumes<br/>cycle detection via visited set
end
BP-->>Caller: { pipeline: ["wiki-content-coherence", "link-verification", ..., "wiki-orchestrator"] }
```
### Composition Metadata Example (brainstorming)
```yaml
composition:
produces: [design-options, risk-surface, brainstorm-output]
consumes: [user-intent]
capabilities: [ideation, design-exploration]
priority: 10
```
`priority` controls execution order when multiple skills produce the same artifact — lower numbers run first.
---
## 8. Bootstrap Flow
At every session start, the AI assistant runs bootstrap to establish context. Source: [`superpowers-augment.js`](../superpowers-augment.js) `bootstrap()`.
```mermaid
sequenceDiagram
participant AI
participant SA as superpowers-augment.js
participant SD as lib/skill-discovery.js
participant WS as lib/workflow-state.js
participant FS as Filesystem
AI->>SA: bootstrap
SA->>FS: write ~/.codex/.superpowers-session<br/>{ bootstrapped: ISO timestamp, pid }
SA->>SA: print protocol header<br/>(skill check rule, auto-triggers, critical gates)
SA->>SD: findAllSkills(personalDir, superpowersDir)
SD->>FS: scan ~/.codex/skills/ (personal — includes bundled obra skills since v2.6.0)
SD->>SD: deduplicateSkills()<br/>personal skills win on name collision
SD-->>SA: deduplicated skill array
SA->>FS: write ~/.codex/.skill-index.json
SA->>SA: emitSkillIndex()<br/>print count + load command summary
SA->>SA: detectAliasCollisions()<br/>warn on stderr (non-fatal)
SA->>WS: getStatus()
alt active workflow exists
WS-->>SA: workflow status line
SA->>AI: print workflow status
end
SA-->>AI: bootstrap output complete
```
### Session Staleness
`checkBootstrap()` reads `~/.codex/.superpowers-session` and checks if age < 4 hours. Skills warn (non-blocking) if bootstrap was not run within the session window. This prevents skills from firing in isolation without the meta-framework context that makes them effective.
### Skill Discovery Priority
As of v2.6.0, `superpowers-augment.js` installs all skills directly into `~/.codex/skills/`, and its own `SUPERPOWERS_SKILLS_DIR` default now points there too, so for the primary CLI the separate `~/.codex/superpowers/skills/` tier no longer exists.
```
~/.codex/skills/<name>/skill.md (personal: the only lookup tier for superpowers-augment.js)
```
Overlay repos (org-specific extensions, etc.) install additional skills into `~/.codex/skills/` alongside the base set; name collisions are resolved by last-installed-wins during `install_skills()`.
**Known drift:** `mcp/superpowers-mcp.js` was not updated for this change. Its `SUPERPOWERS_SKILLS_DIR` default still points at the old `~/.codex/superpowers/skills/` path, independently of `superpowers-augment.js`. If you run the MCP server against a v2.6.0+ install and that old directory does not exist, set `SUPERPOWERS_SKILLS_DIR=~/.codex/skills` explicitly in its environment.
---
## 9. Namespace Resolution
`resolveSkillNamespace()` in [`superpowers-augment.js`](../superpowers-augment.js) maps a skill name (possibly with a prefix) to a file path.
```mermaid
flowchart TD
IN[skill name string]
IN --> DASH{Dash shorthand?}
DASH -->|sp-X| EXP1[expand to superpowers-X<br/>no force flag]
DASH -->|spp-X| EXP2[expand to superpowers-X<br/>forceSpp=true]
DASH -->|spo-X| EXP3[expand to superpowers-X<br/>forceSpo=true]
DASH -->|none| PREFIX
EXP1 --> PREFIX
EXP2 --> FORCE_SPP
EXP3 --> FORCE_SPO
PREFIX{Namespace prefix?}
PREFIX -->|superpowers:| FORCE_SPO2[forceSuperpowers=true<br/>strip prefix]
PREFIX -->|spp:| FORCE_SPP[search SPP_SOURCE_DIR<br/>find skill in domain subdirs]
PREFIX -->|spo:| FORCE_SPO[search SP_OVERLAY_SOURCE_DIR]
PREFIX -->|none| PERSONAL
PERSONAL[search ~/.codex/skills/ personal dir]
PERSONAL -->|found| DONE
PERSONAL -->|not found| ALIAS
ALIAS[resolveAlias: scan all skills for matching alias]
ALIAS -->|found| DONE
ALIAS -->|not found| ERROR[error + similarity suggestions<br/>from matchSkillsTfIdf]
FORCE_SPO2 --> PERSONAL
DONE[return skillFile + actualName]
```
### Prefix Reference
| Prefix | Resolves To | Use Case |
|--------|------------|----------|
| (none) | personal → alias | Normal usage |
| `superpowers:` | personal dir (obra skills bundled there since v2.6.0) | Load a skill by explicit namespace |
| `spp:` | `SPP_SOURCE_DIR` (superpowers-plus source repo) | Load from source, not installed copy |
| `spo:` | `SP_OVERLAY_SOURCE_DIR` (overlay repo source) | Load from overlay source |
| `sp-X` | expands to `superpowers-X`, then normal resolution | Convenience shorthand |
| `spp-X` | expands to `superpowers-X` in spp source | Dev convenience |
| `spo-X` | expands to `superpowers-X` in overlay source | Dev convenience |
`SPP_SOURCE_DIR` defaults to the directory containing `superpowers-augment.js` (self-discovery), falling back to `~/.codex/superpowers-plus`. Set `SUPERPOWERS_SKILLS_DIR` or `PERSONAL_SKILLS_DIR` env vars to override discovery paths.