Files
hyperframes/packages/cli/src/utils/lintFormat.ts
T
Vance IngallsandClaude Opus 4.6 9cbfec1eca feat(skills): add hyperframes-cli skill (#154)
* feat(skills): add hyperframes-cli skill for CLI workflow guidance

Adds a new skill that teaches AI agents how to use the HyperFrames CLI
(init, lint, dev, render, doctor). Previously, agents had no way to
discover the CLI — the compose-video skill only covered HTML authoring.
This led to agents searching for binaries, finding the monorepo, and
running bun run studio manually instead of using npx hyperframes dev.

Also registers the skill in init.ts so new projects get it bundled
alongside hyperframes-compose and hyperframes-captions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): rename dev command to preview

The command starts a preview server — "preview" describes what users
are doing more accurately than "dev". Updates the command name, file
name, all CLI references, docs, skills, and template CLAUDE.md.

22 files updated across CLI source, docs, skills, and templates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(skills): replace stale dev reference with preview in CLI skill

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(docs): catch remaining dev references missed in rename

- testing-local-changes.mdx: two inline command examples
- troubleshooting.mdx: anchor link #dev → #preview, "dev server" → "preview server"
- cli.mdx: "dev server" → "preview server"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 00:30:55 -07:00

68 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { c } from "../ui/colors.js";
import type { ProjectLintResult } from "./lintProject.js";
export interface LintFormatOptions {
/** Show elementId in brackets after the code (default: true) */
showElementId?: boolean;
/** Show summary line with error/warning counts (default: false) */
showSummary?: boolean;
/** Group errors before warnings per file (default: false — interleaved) */
errorsFirst?: boolean;
/** Include info-level findings in output (default: false — only errors/warnings) */
verbose?: boolean;
}
/**
* Format lint findings for console output. Used by lint, render, and preview commands.
*/
export function formatLintFindings(
{ results, totalErrors, totalWarnings, totalInfos }: ProjectLintResult,
options: LintFormatOptions = {},
): string[] {
const {
showElementId = true,
showSummary = false,
errorsFirst = false,
verbose = false,
} = options;
const lines: string[] = [];
const multiFile = results.length > 1;
for (const { file, result } of results) {
if (result.findings.length === 0) continue;
const format = (finding: (typeof result.findings)[0]) => {
if (!verbose && finding.severity === "info") return;
const prefix =
finding.severity === "error"
? c.error("✗")
: finding.severity === "warning"
? c.warn("⚠")
: c.dim("");
const fileLabel = multiFile ? c.dim(`[${file}] `) : "";
const loc =
showElementId && finding.elementId ? ` ${c.accent(`[${finding.elementId}]`)}` : "";
lines.push(` ${prefix} ${fileLabel}${c.bold(finding.code)}${loc}: ${finding.message}`);
if (finding.fixHint) lines.push(` ${c.dim(`Fix: ${finding.fixHint}`)}`);
};
if (errorsFirst) {
for (const f of result.findings) if (f.severity === "error") format(f);
for (const f of result.findings) if (f.severity === "warning") format(f);
if (verbose) for (const f of result.findings) if (f.severity === "info") format(f);
} else {
for (const f of result.findings) format(f);
}
}
if (showSummary) {
const icon = totalErrors > 0 ? c.error("◇") : c.success("◇");
lines.push("");
const summaryParts = [`${totalErrors} error(s)`, `${totalWarnings} warning(s)`];
if (verbose && totalInfos > 0) summaryParts.push(`${totalInfos} info(s)`);
lines.push(`${icon} ${summaryParts.join(", ")}`);
}
return lines;
}