SuperAPI AI Directory

audit-licenses

Security & auditing

View repository

Updated 10-15 21:49

About this skill

/audit-licenses — Dependency License Audit

You audit the open-source licenses of this project's dependencies. The point is compliance: some licenses (GPL, AGPL) force the project that uses them to be open-source under the same terms. The team needs to know that before shipping.

This is an example custom skill. It shows the patterns every nanostack-compatible skill follows: detect the project, do the work, save an artifact so future skills can read it.

Process

0. Resolve paths (host-agnostic)

Every executable snippet below redefines two env vars at the top, so each snippet is copy-paste runnable on its own. Some agents (including Claude Code) execute each tool call in a fresh bash process, so an export in one block does not survive into the next. The defaults assume Claude Code; override the vars for Codex, Cursor, OpenCode, Gemini, or your own host.

NANOSTACK_ROOT="${NANOSTACK_ROOT:-$HOME/.claude/skills/nanostack}"
SKILL_DIR="${SKILL_DIR:-$HOME/.claude/skills/audit-licenses}"

Common substitutions:

Host NANOSTACK_ROOT SKILL_DIR
Claude Code $HOME/.claude/skills/nanostack $HOME/.claude/skills/audit-licenses
Codex / Cursor / OpenCode / Gemini $HOME/.agents/skills/nanostack (or wherever the agent loads skills from) $HOME/.agents/skills/audit-licenses

If the user already exported NANOSTACK_ROOT and SKILL_DIR, the ${VAR:-default} form does not overwrite them.

1. Register the phase (first run only)

save-artifact.sh and the resolver only accept phases listed in .nanostack/config.json. Register audit-licenses once per project:

mkdir -p .nanostack
if [ -f .nanostack/config.json ]; then
  jq '.custom_phases = ((.custom_phases // []) + ["audit-licenses"] | unique)' \
    .nanostack/config.json > .nanostack/config.json.tmp \
    && mv .nanostack/config.json.tmp .nanostack/config.json
else
  printf '%s\n' '{"custom_phases":["audit-licenses"]}' > .nanostack/config.json
fi

Once registered the phase is first-class: the resolver returns phase_kind=custom, the artifact store accepts audit-licenses, and the rest of the lifecycle scripts learn to handle it as PRs 4-6 of the Custom Stack Framework round land.

2. Resolve context

Load whatever upstream context exists for this phase. The resolver knows about audit-licenses because step 1 registered it:

NANOSTACK_ROOT="${NANOSTACK_ROOT:-$HOME/.claude/skills/nanostack}"
"$NANOSTACK_ROOT/bin/resolve.sh" audit-licenses

Output includes phase_kind: "custom" and upstream_artifacts driven by the phase's depends_on (declared in this skill's frontmatter, or in .nanostack/config.json's phase_graph if you have one). Empty upstream is normal for a custom skill that does not declare dependencies — saving an artifact in step 4 still works.

3. Detect the stack and run the audit

Check what kind of project this is and read its dependency manifest. The helper lives next to this SKILL.md:

SKILL_DIR="${SKILL_DIR:-$HOME/.claude/skills/audit-licenses}"
if [ -f package.json ]; then
  "$SKILL_DIR/bin/audit.sh" node
elif [ -f requirements.txt ] || [ -f pyproject.toml ]; then
  "$SKILL_DIR/bin/audit.sh" python
elif [ -f go.mod ]; then
  "$SKILL_DIR/bin/audit.sh" go
else
  echo "No supported manifest found (package.json, requirements.txt, pyproject.toml, go.mod)."
  exit 1
fi

The script prints a JSON block with { permissive: N, weak_copyleft: N, strong_copyleft: N, unknown: N, flagged: [...] } plus a human-readable summary table.

4. Show the result and save the artifact

Show the user the summary first, then save an artifact so a future skill (or /compound) can read it:

NANOSTACK_ROOT="${NANOSTACK_ROOT:-$HOME/.claude/skills/nanostack}"
"$NANOSTACK_ROOT/bin/save-artifact.sh" audit-licenses \
  '{"phase":"audit-licenses","summary":{"flagged":[...],"counts":{...}},"context_checkpoint":{}}'

The artifact lives at .nanostack/audit-licenses/<timestamp>.json. Other skills can find it with "$NANOSTACK_ROOT/bin/find-artifact.sh" audit-licenses 30.

5. Headline

Close with one summary line, same format as the built-in skills:

[audit-licenses] OK: 47 deps scanned, 0 GPL/AGPL flagged.

Use WARN instead of OK when any GPL/AGPL dependency is flagged.

Gotchas

  • This skill only inspects manifest files. Transitive dependencies inside node_modules/, vendor/, or .venv/ are not walked. For deep audits use a dedicated tool like license-checker (npm) or pip-licenses.
  • "Permissive" here means MIT, BSD, Apache-2.0, ISC. "Weak copyleft" means LGPL, MPL. "Strong copyleft" means GPL, AGPL.
  • Unknown licenses are not assumed permissive. They are flagged as unknown and the user decides.