new-component — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited new-component (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are about to add a new component to appCN — a shadcn-philosophy component library for React Native + Expo. Read this entire skill before asking the user any questions.
CLAUDE.md — architecture, monorepo map.DESIGN.md — taste layer + the SOP this skill operationalizes.AGENTS.md — agent-specific rules.Ask only what's missing. You need:
bottom-sheet).base (broad mobile primitive) or ai (featured AIcollection). If unclear, default to base and ask.
that earns the component's place. If the user can't articulate it, push back. Components without a delight detail don't get merged.
packages/ui/src/{components,ai}/<slug>.tsxFile shape (mirror the existing components):
header doc comment ← what it is + the delight detail, in one breath
imports ← react, react-native, reanimated, ../lib/cn, ../lib/motion, optional ../lib/haptics
cva blocks ← <name>Variants / <name>TextVariants (only if there are variants)
Props interface ← exported, named <Name>Props
component ← exported, named <Name>
local sub-components ← Dot, Caret, icons… below the main component
named exports ← incl. variantsNon-negotiables (DESIGN.md):
StyleSheet).PRESS_SCALE from ../lib/motion.../lib/haptics if any tactile feedback is needed.accessibilityRole + label + hitSlop on every interactive surface.useReducedMotion() — fall back to crossfade or settled state.bg-primary, text-muted-foreground) only.Views/borders (see prompt-input.tsx).Don't add an icon library.
packages/ui/src/{components,ai}/<slug>.meta.tsimport type { ComponentMeta } from "../lib/meta";
export const meta: ComponentMeta = {
slug: "<slug>",
title: "<Title Case>",
category: "base" | "ai",
description: "<one line>",
anatomy: "<2–4 sentences>",
delight: "<the one detail, named explicitly>",
props: [
{ name: "...", type: "...", default: "...", description: "..." },
// every public prop, in interface order
],
examples: [
{ title: "Basic", description: "...", code: `...` }, // canonical
// at least one more
],
a11y: ["<bullet 1>", "<bullet 2>", "..."],
};Mirror TSDoc from the component file into props[].description — single source of truth where possible. Examples must be copy-paste runnable.
packages/ui/src/index.tsexport { <Name> } from "./<dir>/<slug>";
export type { <Name>Props } from "./<dir>/<slug>";Also add the meta to packages/ui/src/lib/meta.ts at the bottom:
export { meta as <name>Meta } from "../<dir>/<slug>.meta";Edit apps/showcase/lib/demos.tsx:
<Name> (and any related types) to the import from @app-cn/ui.<Name>Demo() wrapper above the array.demos array:{
slug: "<slug>",
title: "<Title>",
description: "<one line>",
category: "<base|ai>",
render: () => /* the demo */,
},The slug here MUST match the <slug>.tsx filename so /c/<slug> resolves.
Edit apps/web/lib/registry.ts — add an entry to the components array:
{
slug: "<slug>",
title: <name>Meta.title,
description: <name>Meta.description,
category: <name>Meta.category,
sourcePath: "../../packages/ui/src/<dir>/<slug>.tsx",
registryItem: "<slug>",
meta: <name>Meta,
},…and add <name>Meta to the import from @app-cn/ui/lib/meta.
Edit apps/web/registry.json — push to items:
{
"name": "<slug>",
"type": "registry:component",
"title": "<Title>",
"description": "<one line>",
"dependencies": ["<npm packages the component imports>"],
"registryDependencies": ["@app-cn/cn", "@app-cn/motion", "@app-cn/haptics"],
"files": [
{
"path": "../../packages/ui/src/<dir>/<slug>.tsx",
"type": "registry:component",
"target": "components/ui/<slug>.tsx"
}
]
}dependencies → npm packages (class-variance-authority, react-native-reanimated, etc.). registryDependencies → namespaced refs to other appCN registry items (@app-cn/cn always; @app-cn/motion if imported; @app-cn/haptics if imported).
Run, in order:
pnpm typecheck # ui + cli + showcase + web all clean
pnpm registry:build # emits public/r/<slug>.json + validator passes
pnpm --filter showcase start # open /c/<slug>, sanity-check the demo
pnpm --filter @app-cn/web dev # /components/<slug> renders all sectionsIf any step fails, fix it. Don't tell the user the component is done.
After all four pass:
apps/web/public/r/<slug>.json exists and its files[].contentuses @/lib/cn (the import-fix script ran).
possible — web preview can hide motion bugs.
This is required. The Changesets bot blocks PRs that skip it, and the release pipeline can't pick up the bump without one.
pnpm changeset from the repo root.@app-cn/ui (space to toggle, enter to confirm).minor for a new component.patch only for bugfixes to an existing component.
reactive 3D orb that breathes with voice level.`
.changeset/<adjective-noun-verb>.md file is generated.pnpm changeset status shows the bump for @app-cn/ui..changeset/*.md file in the hand-off list below.Report:
.changeset/*.md).
pnpm changeset status).npx @app-cn/cli@latest add <slug> (or the bare-shadcn fallback npx shadcn@latest add http://localhost:3100/r/<slug>.json).
to check it themselves.
Do not commit unless the user asks.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.