Skip to content

feat(cli): skillforge inspect <path> — one-shot validation + lint + summary#14

Merged
adityachilka1 merged 1 commit into
mainfrom
feat/inspect
May 24, 2026
Merged

feat(cli): skillforge inspect <path> — one-shot validation + lint + summary#14
adityachilka1 merged 1 commit into
mainfrom
feat/inspect

Conversation

@adityachilka1
Copy link
Copy Markdown
Owner

What

skillforge inspect <path> — one-shot diagnostic report for a SKILL.md. Eighth piece of the authoring workflow after init, validate, lint, pack, install, update, and format. Where the other commands do one thing, inspect reads — it rolls validation, linting, frontmatter parsing, body stats, and (for directory inputs) the file inventory into one structured report.

# Human-readable mode
skillforge inspect ./code-review
# code-review  /…/SKILL.md  ISSUES
#
# FRONTMATTER
#   name         code-review
#   description  Use this when the user asks for a code review on a diff…
#   version      0.1.0
#   tags         code, review
#
# BODY
#    42  lines
#   210  words
#  1832  characters
#     4  sections
#   headings:
#     · What this skill does
#     · When to use
#     · Examples
#
# VALIDATION
#   ✓ no issues
#
# LINT
#   · warning …/SKILL.md: tags-empty: tags array is empty…
#
# ATTACHED FILES
#   · SKILL.md
#   · templates/letter.md
#
# SUMMARY
#   ✗ validation: 0  lint: 1

# Machine-readable mode for CI
skillforge inspect ./code-review --json

Why

Users today have to run validate, then lint, then cat SKILL.md | head and squint at the frontmatter to understand a skill's shape. inspect rolls those into one structured view — and exposes the same data as a JSON object so CI summaries can be one HTTP-friendly call.

Result shape

interface InspectResult {
  path: string;
  name?: string;                       // from frontmatter
  frontmatter?: SkillFrontmatter;      // zod-validated
  body: {
    lines: number;
    characters: number;
    words: number;
    sections: string[];                // `## headings` in document order
  };
  validation: ValidateResult;          // delegated to validateSkill
  lint: LintResult;                    // delegated to lintSkill
  attachedFiles?: string[];            // directory input only
  summary: {
    ok: boolean;                       // validation passed AND no lint errors
    validationIssues: number;
    lintIssues: number;
  };
}

Semantics

Aspect Behaviour
Input path File (single SKILL.md) or directory (must contain SKILL.md)
Validation Delegated to validateSkill — no reimplementation
Lint Delegated to lintSkill — no reimplementation
Frontmatter Re-parsed once for the typed report; validation issues already surfaced
body.sections Level-2 (##) headings only, document order, fenced-code-aware
attachedFiles Directory mode only; uses pack's exact exclusion rules (.git, node_modules, .DS_Store, *.log, dotfiles)
summary.ok validation.ok && lintErrors === 0 (warnings don't fail the summary)
Side effects None — inspect never writes

Code-fence-aware section parsing

The ## headings extractor tracks fenced-code-block state so a ## Not A Section inside a md block doesn't pollute the section list. Dedicated test pins the behaviour.

Reused exclusion rule

pack.ts exported a new helper shouldExcludeEntry(name) — a minimal extraction of the existing private shouldExclude() function, with pack now delegating to it. No behaviour change in pack. inspect reuses it so the two commands agree on which files belong to the skill.

CLI output taste

  • Sentence-case section headings, dim-uppercase for tracked feel.
  • Frontmatter rendered as a two-column key/value table, key column padded for alignment.
  • Body stats with right-aligned numerals (tabular-numerals analogue) so the eye compares numbers cleanly.
  • Validation and lint issues grouped under their own headings; severity coloured (red for errors, yellow for warnings).
  • Final SUMMARY line with the green check or red cross plus the counts.

Exit codes

Situation Exit
summary.ok true (validation passed, no lint errors) 0
Any validation issue OR any lint error 1
Missing path, no SKILL.md in directory, etc. 1

Same posture as validate / lint.

Surface

  • src/inspect.tsinspectSkill() plus internal helpers (path resolution, code-fence-aware section extraction, body stats, attached-file walker). ~205 LOC. No new runtime deps; composes the existing validateSkill / lintSkill / shouldExcludeEntry APIs.
  • src/inspect.test.ts — 10 tests covering happy SKILL.md, invalid frontmatter, lint TODO error, directory mode + exclusion, level-2 section extraction, fenced-code-block section masking, exact word count, file-not-found, directory-without-SKILL.md, and JSON shape stability.
  • src/cli.ts — new inspect subcommand with --json flag and the human-readable printInspectReport() formatter.
  • src/index.ts — re-exports inspectSkill, InspectOptions, InspectResult, InspectBodyStats, InspectSummary.
  • src/pack.ts — exports a new shouldExcludeEntry(name) helper and delegates the existing private function to it. No behavioural change (verified by the unchanged pack tests).
  • README.md — new ### skillforge inspect <path> section; status line updated.
  • CHANGELOG.mdUnreleased entry.

Gates

Check Status
pnpm install no drift
pnpm typecheck (tsc --noEmit) clean
pnpm lint (biome) clean
pnpm test (vitest) 111/111 pass (10 new + 101 existing)
pnpm build (tsup) ESM + DTS build success
Smoke: ./dist/cli.js init demo && ./dist/cli.js inspect demo exits 1 (template's TODO markers surface as lint errors and validation warnings)
Smoke: ./dist/cli.js inspect demo --json exits 1, emits well-formed JSON with all top-level keys

On inspect vs validate / lint

validate is the schema gate. lint is the style critic. inspect is the reader: it doesn't add new rules — it joins what the other commands already know into one report a human can scan in a second. The three compose; you can still run them individually.

Declaration of AI-Tools / LLMs usage

  • Claude (Opus) for design, implementation, tests, commit message, this PR body — reviewed by @adityachilka1 before push.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Warning

Review limit reached

@adityachilka1, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 57 minutes and 48 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a464d093-210c-4e33-89ea-c0adff1c3424

📥 Commits

Reviewing files that changed from the base of the PR and between c9cf4cd and ba612c6.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • README.md
  • src/cli.ts
  • src/index.ts
  • src/inspect.test.ts
  • src/inspect.ts
  • src/pack.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/inspect

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@adityachilka1 adityachilka1 merged commit 986098d into main May 24, 2026
4 checks passed
@adityachilka1 adityachilka1 deleted the feat/inspect branch May 24, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants