Create your own skill

Scaffold a custom skill with one script, validate it with another, and let the same lifecycle as the built-in phases handle artifacts, journals, analytics, and conductor scheduling.

1. Scaffold the skill

Use bin/create-skill.sh from the nanostack repo root. The script writes SKILL.md, agents/openai.yaml, and the directory layout the framework expects.

bin/create-skill.sh license-audit --concurrency read --depends-on build

--concurrency declares whether the phase reads or writes. Read-only phases can run in parallel and are blocked from writing by guard. --depends-on declares which upstream phase produced the artifact this skill needs. The resolver uses it to populate phase_context.

2. Check the contract

bin/check-custom-skill.sh validates the skill against the Custom Stack Framework contract: required files, frontmatter shape, concurrency value, depends_on graph, and artifact schema.

bin/check-custom-skill.sh .nanostack/skills/license-audit

The validator runs locally and is also the gate the contract test runs in CI. Treat a passing check as the contract bar for any custom skill.

3. Where the skill lives

Skills resolve through the Nanostack store, not a hardcoded host directory. By default the store is .nanostack/skills/ in the project, with $NANOSTACK_STORE as an override. The same resolver is what host adapters use to surface the skill in their UI, so you do not symlink into ~/.claude/skills manually.

4. Anatomy of a custom skill

.nanostack/skills/license-audit/
├── SKILL.md             # frontmatter + agent instructions
├── agents/
│   └── openai.yaml      # adapter-specific behavior (read by the host)
└── references/          # optional, domain knowledge the skill reads

The frontmatter declares how the framework treats the skill, not just metadata for the host. The required fields are:

---
name: license-audit
description: Audit third-party licenses before release.
concurrency: read           # or "write" or "exclusive"
depends_on:
  - build                   # one or more upstream phases
phase_kind: custom
artifact_schema: artifacts/license-audit.schema.json
---

5. Register the phase

Add the skill to .nanostack/config.json so the resolver, conductor, and guard treat it as a real phase. The order in phase_graph drives upstream lookups, gating, and sprint journal entries.

{
  "custom_phases": ["license-audit"],
  "phase_graph": {
    "license-audit": {
      "depends_on": ["build"],
      "before": ["security"]
    }
  }
}

Use phase_graph when the skill is part of a custom stack with multiple new phases. Use plain custom_phases plus the frontmatter depends_on for one-off skills.

6. What the skill gets for free

Registering a custom phase plugs it into the same lifecycle as the built-in phases. None of this requires extra wiring inside the skill body:

  • save-artifact.sh and find-artifact.sh accept the custom phase name, validate the artifact schema, and add the SHA-256 integrity field strict consumers can require.
  • resolve.sh returns phase_kind: "custom" for the skill, plus the upstream artifacts driven by depends_on or phase_graph.
  • Skills read upstream context through the resolver. The resolver returns phase_context, routing.trust, and upstream_status in the same JSON object as built-in phases see.
  • The sprint journal and analytics include the phase. It shows up in timelines and per-phase stats automatically.
  • The conductor can schedule the skill and reads its concurrency metadata. Read-only phases parallelize; exclusive ones serialize.
  • Guard's phase-aware tier covers the custom phase. A read-only custom phase blocks writes the same way a built-in read-only phase does.

7. Use it

# From inside the host (Claude Code shown):
/license-audit

# The host reads the resolved skill, runs the SKILL.md process,
# and saves the artifact through bin/save-artifact.sh.

Further reading

PreviousHooksNextCustom phases