claude-code-superkit 0.0.0-stage → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +374 -2
- package/bin/cli.js +153 -0
- package/bin/inject-tokens.js +224 -0
- package/bin/measure-tokens.js +17 -0
- package/bin/superkit-counts-verify.sh +30 -0
- package/lib/codex.js +246 -0
- package/lib/docs-scaffold.js +147 -0
- package/lib/installer.js +499 -0
- package/lib/prompts.js +51 -0
- package/lib/settings-builder.js +51 -0
- package/lib/superpowers.js +99 -0
- package/lib/utils.js +117 -0
- package/lib/validator.js +84 -0
- package/package.json +49 -4
- package/packages/codex/AGENTS.md +396 -0
- package/packages/codex/INSTALL.md +342 -0
- package/packages/codex/config.toml +22 -0
- package/packages/codex/hooks/superkit.mjs +203 -0
- package/packages/codex/hooks.json +30 -0
- package/packages/codex/legacy-baseline.json +88 -0
- package/packages/codex/native-skills.txt +65 -0
- package/packages/codex/rules/default.rules +565 -0
- package/packages/codex/skills/ai-slop-cleaner/SKILL.md +44 -0
- package/packages/codex/skills/api-contract-sync/SKILL.md +96 -0
- package/packages/codex/skills/architect/SKILL.md +49 -0
- package/packages/codex/skills/audit-backend/SKILL.md +80 -0
- package/packages/codex/skills/audit-frontend/SKILL.md +82 -0
- package/packages/codex/skills/audit-infra/SKILL.md +87 -0
- package/packages/codex/skills/audit-orchestrator/SKILL.md +114 -0
- package/packages/codex/skills/behavioral-nudge-engine/SKILL.md +110 -0
- package/packages/codex/skills/benchmark/SKILL.md +49 -0
- package/packages/codex/skills/bot-reviewer/SKILL.md +94 -0
- package/packages/codex/skills/code-reviewer/SKILL.md +67 -0
- package/packages/codex/skills/codebase-onboarding-engineer/SKILL.md +46 -0
- package/packages/codex/skills/comment-rot-analyzer/SKILL.md +75 -0
- package/packages/codex/skills/commit-helper/SKILL.md +101 -0
- package/packages/codex/skills/critic/SKILL.md +56 -0
- package/packages/codex/skills/database-reviewer/SKILL.md +79 -0
- package/packages/codex/skills/debug-observer/SKILL.md +107 -0
- package/packages/codex/skills/dependency-checker/SKILL.md +69 -0
- package/packages/codex/skills/design-system-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/dev-orchestrator/SKILL.md +304 -0
- package/packages/codex/skills/docs-reviewer/SKILL.md +86 -0
- package/packages/codex/skills/drizzle-orm-expert/SKILL.md +246 -0
- package/packages/codex/skills/e2e-test-generator/SKILL.md +95 -0
- package/packages/codex/skills/evaluator/SKILL.md +63 -0
- package/packages/codex/skills/frontend-perf-reviewer/SKILL.md +95 -0
- package/packages/codex/skills/frontend-ui-color-reviewer/SKILL.md +68 -0
- package/packages/codex/skills/frontend-ui-design-critic/SKILL.md +99 -0
- package/packages/codex/skills/frontend-ui-interaction-reviewer/SKILL.md +102 -0
- package/packages/codex/skills/frontend-ui-motion-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/frontend-ui-reviewer/SKILL.md +81 -0
- package/packages/codex/skills/frontend-ui-typography-reviewer/SKILL.md +62 -0
- package/packages/codex/skills/gltf-debugging/SKILL.md +128 -0
- package/packages/codex/skills/go-benchmark/SKILL.md +217 -0
- package/packages/codex/skills/go-concurrency-reviewer/SKILL.md +113 -0
- package/packages/codex/skills/go-error-reviewer/SKILL.md +107 -0
- package/packages/codex/skills/go-grpc-patterns/SKILL.md +285 -0
- package/packages/codex/skills/go-modernizer/SKILL.md +111 -0
- package/packages/codex/skills/go-observability-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/go-performance-reviewer/SKILL.md +112 -0
- package/packages/codex/skills/go-reviewer/SKILL.md +109 -0
- package/packages/codex/skills/go-samber-do/SKILL.md +158 -0
- package/packages/codex/skills/go-samber-lo/SKILL.md +178 -0
- package/packages/codex/skills/go-samber-oops/SKILL.md +174 -0
- package/packages/codex/skills/goal-verifier/SKILL.md +53 -0
- package/packages/codex/skills/health-checker/SKILL.md +109 -0
- package/packages/codex/skills/html-to-3d-texture/SKILL.md +153 -0
- package/packages/codex/skills/impeccable-craft/SKILL.md +101 -0
- package/packages/codex/skills/lint-runner/SKILL.md +85 -0
- package/packages/codex/skills/migrate/SKILL.md +60 -0
- package/packages/codex/skills/migration-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/minimal-change-engineer/SKILL.md +44 -0
- package/packages/codex/skills/new-migration/SKILL.md +59 -0
- package/packages/codex/skills/nextjs-supabase-auth/SKILL.md +227 -0
- package/packages/codex/skills/output-enforcement/SKILL.md +71 -0
- package/packages/codex/skills/plan-checker/SKILL.md +53 -0
- package/packages/codex/skills/postgresql-optimization/SKILL.md +159 -0
- package/packages/codex/skills/pre-deploy-validator/SKILL.md +111 -0
- package/packages/codex/skills/presentation-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/product-3d-lighting/SKILL.md +137 -0
- package/packages/codex/skills/project-architecture/SKILL.md +52 -0
- package/packages/codex/skills/py-reviewer/SKILL.md +100 -0
- package/packages/codex/skills/r3f-scene-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/r3f-scroll-driven-3d/SKILL.md +162 -0
- package/packages/codex/skills/reality-checker/SKILL.md +61 -0
- package/packages/codex/skills/redis-patterns/SKILL.md +260 -0
- package/packages/codex/skills/review-orchestrator/SKILL.md +151 -0
- package/packages/codex/skills/rs-reviewer/SKILL.md +98 -0
- package/packages/codex/skills/ru-text/SKILL.md +132 -0
- package/packages/codex/skills/scaffold-endpoint/SKILL.md +44 -0
- package/packages/codex/skills/security-scanner/SKILL.md +94 -0
- package/packages/codex/skills/silent-failure-hunter/SKILL.md +176 -0
- package/packages/codex/skills/telegram-bot-builder/SKILL.md +120 -0
- package/packages/codex/skills/test-generator/SKILL.md +79 -0
- package/packages/codex/skills/test-runner/SKILL.md +101 -0
- package/packages/codex/skills/threejs-color-management/SKILL.md +97 -0
- package/packages/codex/skills/tree-generator/SKILL.md +63 -0
- package/packages/codex/skills/ts-reviewer/SKILL.md +90 -0
- package/packages/codex/skills/ui-design-reviewer/SKILL.md +89 -0
- package/packages/codex/skills/ui-reviewer/SKILL.md +103 -0
- package/packages/codex/skills/visual-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/writing-agents/SKILL.md +165 -0
- package/packages/codex/skills/writing-commands/SKILL.md +173 -0
- package/packages/core/CLAUDE.md +118 -0
- package/packages/core/INTERNAL-FILES +16 -0
- package/packages/core/agents/ai-slop-cleaner.md +187 -0
- package/packages/core/agents/api-contract-sync.md +127 -0
- package/packages/core/agents/architect.md +205 -0
- package/packages/core/agents/audit-backend.md +137 -0
- package/packages/core/agents/audit-frontend.md +129 -0
- package/packages/core/agents/audit-infra.md +182 -0
- package/packages/core/agents/behavioral-nudge-engine.md +170 -0
- package/packages/core/agents/code-reviewer.md +195 -0
- package/packages/core/agents/codebase-onboarding-engineer.md +172 -0
- package/packages/core/agents/comment-rot-analyzer.md +115 -0
- package/packages/core/agents/critic.md +172 -0
- package/packages/core/agents/database-reviewer.md +201 -0
- package/packages/core/agents/debug-observer.md +261 -0
- package/packages/core/agents/dependency-checker.md +199 -0
- package/packages/core/agents/docs-reviewer.md +206 -0
- package/packages/core/agents/e2e-test-generator.md +261 -0
- package/packages/core/agents/evaluator.md +141 -0
- package/packages/core/agents/goal-verifier.md +130 -0
- package/packages/core/agents/health-checker.md +194 -0
- package/packages/core/agents/migration-reviewer.md +161 -0
- package/packages/core/agents/minimal-change-engineer.md +219 -0
- package/packages/core/agents/plan-checker.md +139 -0
- package/packages/core/agents/pre-deploy-validator.md +189 -0
- package/packages/core/agents/reality-checker.md +175 -0
- package/packages/core/agents/scaffold-endpoint.md +162 -0
- package/packages/core/agents/security-scanner.md +236 -0
- package/packages/core/agents/silent-failure-hunter.md +276 -0
- package/packages/core/agents/test-generator.md +146 -0
- package/packages/core/agents/tree-generator.md +141 -0
- package/packages/core/agents/ui-reviewer.md +172 -0
- package/packages/core/agents/visual-reviewer.md +211 -0
- package/packages/core/commands/audit.md +166 -0
- package/packages/core/commands/benchmark.md +130 -0
- package/packages/core/commands/commit.md +148 -0
- package/packages/core/commands/dev.md +302 -0
- package/packages/core/commands/docs-init.md +75 -0
- package/packages/core/commands/lint.md +137 -0
- package/packages/core/commands/migrate.md +146 -0
- package/packages/core/commands/new-migration.md +182 -0
- package/packages/core/commands/pair.md +209 -0
- package/packages/core/commands/review.md +195 -0
- package/packages/core/commands/security-scan.md +142 -0
- package/packages/core/commands/superkit-evolve.md +231 -0
- package/packages/core/commands/superkit-init.md +274 -0
- package/packages/core/commands/test.md +108 -0
- package/packages/core/commands/workflow.md +150 -0
- package/packages/core/docs/guide/01-getting-started.md +41 -0
- package/packages/core/docs-templates/README.md +33 -0
- package/packages/core/docs-templates/adr-template.md +62 -0
- package/packages/core/docs-templates/architecture/api-contracts.md +26 -0
- package/packages/core/docs-templates/architecture/api-reference.md +48 -0
- package/packages/core/docs-templates/architecture/auth-and-sessions.md +38 -0
- package/packages/core/docs-templates/architecture/backend-layers.md +42 -0
- package/packages/core/docs-templates/architecture/data-flow.md +26 -0
- package/packages/core/docs-templates/architecture/database-schema.md +51 -0
- package/packages/core/docs-templates/architecture/deployment.md +41 -0
- package/packages/core/docs-templates/architecture/frontend-state.md +46 -0
- package/packages/core/helpers/statusline.cjs +370 -0
- package/packages/core/hooks/CHAIN-SEMANTICS.md +84 -0
- package/packages/core/hooks/audit-settings-source.sh +98 -0
- package/packages/core/hooks/audit-trail.sh +120 -0
- package/packages/core/hooks/block-dangerous-git.sh +189 -0
- package/packages/core/hooks/bundle-import-check.sh +64 -0
- package/packages/core/hooks/compact-state-inject.sh +84 -0
- package/packages/core/hooks/config-protection.sh +68 -0
- package/packages/core/hooks/console-log-warning.sh +28 -0
- package/packages/core/hooks/context-monitor.sh +35 -0
- package/packages/core/hooks/dev-edit-counter.sh +59 -0
- package/packages/core/hooks/dev-marker-set.sh +55 -0
- package/packages/core/hooks/dev-required-on-commit.sh +426 -0
- package/packages/core/hooks/doc-check-on-commit.sh +396 -0
- package/packages/core/hooks/edit-streak-check.sh +63 -0
- package/packages/core/hooks/evolve-check.sh +78 -0
- package/packages/core/hooks/gateguard-pre-edit.sh +154 -0
- package/packages/core/hooks/gateguard-record-facts.sh +37 -0
- package/packages/core/hooks/intake-classifier.py +449 -0
- package/packages/core/hooks/lib/profile.sh +141 -0
- package/packages/core/hooks/loop-guard.sh +75 -0
- package/packages/core/hooks/migration-safety.sh +56 -0
- package/packages/core/hooks/plan-completion-gate.sh +61 -0
- package/packages/core/hooks/pre-compact-save.sh +89 -0
- package/packages/core/hooks/security-patterns.sh +119 -0
- package/packages/core/hooks/session-context-restore.sh +76 -0
- package/packages/core/hooks/subagent-stop-validate.sh +73 -0
- package/packages/core/hooks/superkit-counts-verify.sh +346 -0
- package/packages/core/hooks/superkit-update.sh +367 -0
- package/packages/core/hooks/tests/README.md +42 -0
- package/packages/core/hooks/tests/audit-trail-chain_test.sh +62 -0
- package/packages/core/hooks/tests/block-dangerous-git_test.sh +144 -0
- package/packages/core/hooks/tests/chain-semantics/h1.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/h2.sh +9 -0
- package/packages/core/hooks/tests/chain-semantics/h3.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/run-experiment.sh +65 -0
- package/packages/core/hooks/tests/chain-semantics/settings-experiment.json +15 -0
- package/packages/core/hooks/tests/counts-verify_test.sh +118 -0
- package/packages/core/hooks/tests/dev-required-on-commit_test.sh +207 -0
- package/packages/core/hooks/tests/dev-required-wip-on-main_test.sh +20 -0
- package/packages/core/hooks/tests/doc-check-on-commit_test.sh +122 -0
- package/packages/core/hooks/tests/edit-streak-check_test.sh +106 -0
- package/packages/core/hooks/tests/internal-manifest_test.sh +130 -0
- package/packages/core/hooks/tests/json-path_test.sh +108 -0
- package/packages/core/hooks/tests/mirror-invariants_test.sh +139 -0
- package/packages/core/hooks/tests/nudge-throttle_test.sh +95 -0
- package/packages/core/hooks/tests/profile-helper_test.sh +21 -0
- package/packages/core/hooks/tests/run-all.sh +47 -0
- package/packages/core/hooks/tests/session-key-helper_test.sh +17 -0
- package/packages/core/hooks/tests/superkit-update_test.sh +311 -0
- package/packages/core/hooks/tests/warn-visibility_test.sh +59 -0
- package/packages/core/hooks/user-intent-detect.sh +44 -0
- package/packages/core/hooks/verify-hooks.sh +69 -0
- package/packages/core/rules/auto-commands.md +124 -0
- package/packages/core/rules/coding-style.md +68 -0
- package/packages/core/rules/dev-workflow.md +77 -0
- package/packages/core/rules/documentation.md +106 -0
- package/packages/core/rules/frontend-aesthetics.md +53 -0
- package/packages/core/rules/git-workflow.md +14 -0
- package/packages/core/rules/security.md +29 -0
- package/packages/core/rules/superkit-integrity.md +114 -0
- package/packages/core/settings.json +229 -0
- package/packages/core/skills/drizzle-orm-expert/SKILL.md +260 -0
- package/packages/core/skills/nextjs-supabase-auth/SKILL.md +259 -0
- package/packages/core/skills/postgresql-optimization/SKILL.md +150 -0
- package/packages/core/skills/project-architecture/SKILL.md +31 -0
- package/packages/core/skills/project-scanner/SKILL.md +132 -0
- package/packages/core/skills/redis-patterns/SKILL.md +261 -0
- package/packages/core/skills/ru-text/SKILL.md +156 -0
- package/packages/core/skills/telegram-bot-builder/SKILL.md +145 -0
- package/packages/core/skills/writing-agents/SKILL.md +220 -0
- package/packages/core/skills/writing-commands/SKILL.md +176 -0
- package/packages/core/skills/writing-hooks/SKILL.md +335 -0
- package/packages/extras/bot-reviewer.md +279 -0
- package/packages/extras/design-system-reviewer.md +234 -0
- package/packages/extras/red-blue-auditor/README.md +117 -0
- package/packages/extras/red-blue-auditor/agent.md +128 -0
- package/packages/extras/red-blue-auditor/patterns/agent-config.txt +4 -0
- package/packages/extras/red-blue-auditor/patterns/hook-injection.txt +8 -0
- package/packages/extras/red-blue-auditor/patterns/mcp-risk.txt +5 -0
- package/packages/extras/red-blue-auditor/patterns/permission-abuse.txt +6 -0
- package/packages/extras/red-blue-auditor/patterns/secrets.txt +17 -0
- package/packages/extras/red-blue-auditor/scan.sh +88 -0
- package/packages/extras/skillsmp-search/SKILL.md +134 -0
- package/packages/frontend-3d/README.md +62 -0
- package/packages/frontend-3d/agents/frontend-perf-reviewer.md +164 -0
- package/packages/frontend-3d/agents/presentation-reviewer.md +146 -0
- package/packages/frontend-3d/agents/r3f-scene-reviewer.md +128 -0
- package/packages/frontend-3d/agents/ui-design-reviewer.md +169 -0
- package/packages/frontend-3d/commands/capture-screen.md +166 -0
- package/packages/frontend-3d/hooks/bundle-size-warn.sh +93 -0
- package/packages/frontend-3d/hooks/gsap-pattern-check.sh +74 -0
- package/packages/frontend-3d/hooks/r3f-color-check.sh +76 -0
- package/packages/frontend-3d/hooks/tailwind-version-guard.sh +98 -0
- package/packages/frontend-3d/rules/frontend-aesthetics-3d.md +81 -0
- package/packages/frontend-3d/rules/gsap-conventions.md +129 -0
- package/packages/frontend-3d/rules/threejs-conventions.md +116 -0
- package/packages/frontend-3d/skills/gltf-debugging/SKILL.md +145 -0
- package/packages/frontend-3d/skills/html-to-3d-texture/SKILL.md +183 -0
- package/packages/frontend-3d/skills/output-enforcement/SKILL.md +79 -0
- package/packages/frontend-3d/skills/product-3d-lighting/SKILL.md +166 -0
- package/packages/frontend-3d/skills/r3f-scroll-driven-3d/SKILL.md +209 -0
- package/packages/frontend-3d/skills/threejs-color-management/SKILL.md +111 -0
- package/packages/frontend-ui/NOTICE.md +99 -0
- package/packages/frontend-ui/README.md +59 -0
- package/packages/frontend-ui/agents/ui-color-reviewer.md +174 -0
- package/packages/frontend-ui/agents/ui-design-critic.md +198 -0
- package/packages/frontend-ui/agents/ui-interaction-reviewer.md +259 -0
- package/packages/frontend-ui/agents/ui-motion-reviewer.md +266 -0
- package/packages/frontend-ui/agents/ui-reviewer.md +251 -0
- package/packages/frontend-ui/agents/ui-typography-reviewer.md +222 -0
- package/packages/frontend-ui/hooks/tests/ui-animation-easing-check_test.sh +78 -0
- package/packages/frontend-ui/hooks/tests/ui-banned-fonts-check_test.sh +77 -0
- package/packages/frontend-ui/hooks/tests/ui-color-check_test.sh +75 -0
- package/packages/frontend-ui/hooks/ui-animation-easing-check.sh +86 -0
- package/packages/frontend-ui/hooks/ui-banned-fonts-check.sh +90 -0
- package/packages/frontend-ui/hooks/ui-color-check.sh +102 -0
- package/packages/frontend-ui/rules/color-and-contrast.md +230 -0
- package/packages/frontend-ui/rules/frontend-design-aesthetics.md +124 -0
- package/packages/frontend-ui/rules/interaction-polish.md +335 -0
- package/packages/frontend-ui/rules/motion-and-animation.md +283 -0
- package/packages/frontend-ui/rules/spatial-and-layout.md +212 -0
- package/packages/frontend-ui/rules/typography-guidelines.md +185 -0
- package/packages/frontend-ui/rules/ui-anti-patterns.md +309 -0
- package/packages/frontend-ui/settings.json +24 -0
- package/packages/frontend-ui/skills/impeccable-craft/SKILL.md +187 -0
- package/packages/gan/README.md +232 -0
- package/packages/gan/agents/gan-evaluator.md +214 -0
- package/packages/gan/agents/gan-generator.md +171 -0
- package/packages/gan/agents/gan-planner.md +206 -0
- package/packages/gan/rubrics/functionality.md +66 -0
- package/packages/gan/rubrics/ui-quality.md +77 -0
- package/packages/gan/skills/gan-evaluator/SKILL.md +91 -0
- package/packages/gan/skills/gan-generator/SKILL.md +72 -0
- package/packages/gan/skills/gan-planner/SKILL.md +93 -0
- package/packages/stack-agents/go/go-concurrency-reviewer.md +210 -0
- package/packages/stack-agents/go/go-error-reviewer.md +187 -0
- package/packages/stack-agents/go/go-modernizer.md +160 -0
- package/packages/stack-agents/go/go-observability-reviewer.md +185 -0
- package/packages/stack-agents/go/go-performance-reviewer.md +160 -0
- package/packages/stack-agents/go/go-reviewer.md +277 -0
- package/packages/stack-agents/go/references/benchmark-methodology.md +280 -0
- package/packages/stack-agents/go/references/channel-patterns.md +384 -0
- package/packages/stack-agents/go/references/cli-cobra-viper.md +190 -0
- package/packages/stack-agents/go/references/code-style.md +262 -0
- package/packages/stack-agents/go/references/context-propagation.md +317 -0
- package/packages/stack-agents/go/references/data-structures.md +315 -0
- package/packages/stack-agents/go/references/database-patterns.md +334 -0
- package/packages/stack-agents/go/references/design-patterns.md +411 -0
- package/packages/stack-agents/go/references/di-frameworks.md +146 -0
- package/packages/stack-agents/go/references/error-creation.md +251 -0
- package/packages/stack-agents/go/references/error-inspection.md +348 -0
- package/packages/stack-agents/go/references/error-wrapping.md +230 -0
- package/packages/stack-agents/go/references/gopls-driving.md +62 -0
- package/packages/stack-agents/go/references/goroutine-lifecycle.md +351 -0
- package/packages/stack-agents/go/references/graphql-patterns.md +221 -0
- package/packages/stack-agents/go/references/grpc-patterns.md +373 -0
- package/packages/stack-agents/go/references/modernize-guide.md +522 -0
- package/packages/stack-agents/go/references/module-management.md +191 -0
- package/packages/stack-agents/go/references/naming-conventions.md +176 -0
- package/packages/stack-agents/go/references/observability-pipeline.md +352 -0
- package/packages/stack-agents/go/references/performance-profiling.md +250 -0
- package/packages/stack-agents/go/references/refactoring-mechanics.md +127 -0
- package/packages/stack-agents/go/references/rest-openapi-patterns.md +160 -0
- package/packages/stack-agents/go/references/samber-do.md +201 -0
- package/packages/stack-agents/go/references/samber-libraries.md +363 -0
- package/packages/stack-agents/go/references/samber-lo.md +260 -0
- package/packages/stack-agents/go/references/samber-oops.md +200 -0
- package/packages/stack-agents/go/references/security-checklist.md +441 -0
- package/packages/stack-agents/go/references/standard-stdlib-now.md +181 -0
- package/packages/stack-agents/go/references/stay-updated.md +147 -0
- package/packages/stack-agents/go/references/structs-interfaces.md +312 -0
- package/packages/stack-agents/go/references/sync-primitives.md +395 -0
- package/packages/stack-agents/go/references/testing-patterns.md +483 -0
- package/packages/stack-agents/go/references/troubleshooting.md +98 -0
- package/packages/stack-agents/python/py-reviewer.md +194 -0
- package/packages/stack-agents/rust/rs-reviewer.md +188 -0
- package/packages/stack-agents/typescript/ts-reviewer.md +135 -0
- package/packages/stack-hooks/go/go-context-check-on-edit.sh +56 -0
- package/packages/stack-hooks/go/go-error-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-format-on-edit.sh +32 -0
- package/packages/stack-hooks/go/go-safety-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-vet-on-edit.sh +61 -0
- package/packages/stack-hooks/go/golangci-lint-on-edit.sh +54 -0
- package/packages/stack-hooks/python/ruff-on-edit.sh +67 -0
- package/packages/stack-hooks/rust/cargo-check-on-edit.sh +64 -0
- package/packages/stack-hooks/typescript/typecheck-on-edit.sh +76 -0
- package/packages/stack-rules/go/go-conventions.md +44 -0
- package/packages/stack-rules/go/go-safety.md +35 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -u
|
|
3
|
+
HOOK=$(cd "$(dirname "$0")/.." && pwd)/ui-color-check.sh
|
|
4
|
+
PASS=0; FAIL=0
|
|
5
|
+
|
|
6
|
+
expect_warn() {
|
|
7
|
+
local name="$1"; local needle="$2"; local payload="$3"
|
|
8
|
+
local out
|
|
9
|
+
out=$(echo "$payload" | bash "$HOOK" 2>&1 >/dev/null || true)
|
|
10
|
+
if echo "$out" | grep -q "$needle"; then
|
|
11
|
+
echo " ✓ $name"; PASS=$((PASS + 1))
|
|
12
|
+
else
|
|
13
|
+
echo " ✗ $name — expected warning containing '$needle', got: $(echo "$out" | head -2)"
|
|
14
|
+
FAIL=$((FAIL + 1))
|
|
15
|
+
fi
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
expect_silent() {
|
|
19
|
+
local name="$1"; local payload="$2"
|
|
20
|
+
local out
|
|
21
|
+
out=$(echo "$payload" | bash "$HOOK" 2>&1 >/dev/null || true)
|
|
22
|
+
if [ -z "$out" ]; then
|
|
23
|
+
echo " ✓ $name"; PASS=$((PASS + 1))
|
|
24
|
+
else
|
|
25
|
+
echo " ✗ $name — expected silent, got: $(echo "$out" | head -1)"
|
|
26
|
+
FAIL=$((FAIL + 1))
|
|
27
|
+
fi
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
echo "── ui-color-check.sh tests ──"
|
|
31
|
+
|
|
32
|
+
expect_warn "A) pure #000 in color" "Pure #000 or #fff" \
|
|
33
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":".a{color:#000;}"}}'
|
|
34
|
+
|
|
35
|
+
expect_warn "B) pure #fff in background" "Pure #000 or #fff" \
|
|
36
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":".b{background:#fff;}"}}'
|
|
37
|
+
|
|
38
|
+
expect_warn "C) rgb(0,0,0) in color" "Pure rgb" \
|
|
39
|
+
'{"tool_input":{"file_path":"/tmp/x.tsx","new_string":"const s={color:\"rgb(0, 0, 0)\"};"}}'
|
|
40
|
+
|
|
41
|
+
expect_warn "D) Tailwind bg-black" "bg-black/bg-white" \
|
|
42
|
+
'{"tool_input":{"file_path":"/tmp/x.tsx","new_string":"<div className=\"bg-black text-white\">"}}'
|
|
43
|
+
|
|
44
|
+
expect_warn "E) gradient text (background-clip+linear-gradient)" "Gradient text detected" \
|
|
45
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":"h1{background:linear-gradient(45deg,#f00,#00f);background-clip:text;color:transparent;}"}}'
|
|
46
|
+
|
|
47
|
+
expect_warn "F) purple-to-blue gradient" "Purple→blue gradient" \
|
|
48
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":".hero{background:linear-gradient(135deg, purple 0%, blue 100%);}"}}'
|
|
49
|
+
|
|
50
|
+
expect_warn "G) 3+ hsl without oklch" "Multiple hsl" \
|
|
51
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":":root{--a:hsl(0 50% 50%);--b:hsl(120 50% 50%);--c:hsl(240 50% 50%);}"}}'
|
|
52
|
+
|
|
53
|
+
expect_silent "H) oklch-only palette silent" \
|
|
54
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":":root{--a:oklch(50% 0.1 260);--b:oklch(40% 0.1 260);}"}}'
|
|
55
|
+
|
|
56
|
+
expect_silent "I) Non-UI file silent" \
|
|
57
|
+
'{"tool_input":{"file_path":"/tmp/x.go","new_string":"func black() string { return \"#000\" }"}}'
|
|
58
|
+
|
|
59
|
+
expect_silent "J) box-shadow with rgba(0,0,0,0.5) — not a color declaration on color/background" \
|
|
60
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":".a{box-shadow:0 2px 4px rgba(0,0,0,0.5);}"}}'
|
|
61
|
+
|
|
62
|
+
expect_silent "K) Single hsl (not palette) silent" \
|
|
63
|
+
'{"tool_input":{"file_path":"/tmp/x.css","new_string":".a{color:hsl(200 50% 50%);}"}}'
|
|
64
|
+
|
|
65
|
+
out=$(echo '{"tool_input":{"file_path":"/tmp/x.css","new_string":".a{color:#000;}"}}' | CLAUDE_DISABLE_UI_COLOR_CHECK=1 bash "$HOOK" 2>&1 >/dev/null || true)
|
|
66
|
+
if [ -z "$out" ]; then
|
|
67
|
+
echo " ✓ L) Opt-out via CLAUDE_DISABLE_UI_COLOR_CHECK"; PASS=$((PASS + 1))
|
|
68
|
+
else
|
|
69
|
+
echo " ✗ L) Opt-out failed"; FAIL=$((FAIL + 1))
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "── Results ──"
|
|
74
|
+
echo " Pass: $PASS Fail: $FAIL"
|
|
75
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ui-animation-easing-check.sh — warns on ease-in, transition: all, scale(0)
|
|
3
|
+
# Triggers on: PostToolUse (Edit|Write)
|
|
4
|
+
# Profile: all (advisory only, never blocks)
|
|
5
|
+
# Opt-out: CLAUDE_DISABLE_UI_ANIM_CHECK=1
|
|
6
|
+
#
|
|
7
|
+
# Flags motion anti-patterns from motion-and-animation.md and
|
|
8
|
+
# ui-anti-patterns.md:
|
|
9
|
+
# - ease-in on UI transitions/animations (sluggish; use ease-out)
|
|
10
|
+
# - transition: all (animates layout props; specify exact)
|
|
11
|
+
# - scale(0) as entry animation (use scale(0.95))
|
|
12
|
+
# - Animating width/height/top/left/margin (not compositor-accelerated)
|
|
13
|
+
|
|
14
|
+
# Unified profile + disable check
|
|
15
|
+
SUPERKIT_PROFILE_LIB="$(dirname "$0")/lib/profile.sh"
|
|
16
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] || SUPERKIT_PROFILE_LIB="$(dirname "$0")/../lib/profile.sh"
|
|
17
|
+
# shellcheck source=/dev/null
|
|
18
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] && source "$SUPERKIT_PROFILE_LIB" && should_skip_hook "$(basename "$0" .sh)" && exit 0
|
|
19
|
+
|
|
20
|
+
if [ "${CLAUDE_DISABLE_UI_ANIM_CHECK:-}" = "1" ]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
25
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .file_path // empty' 2>/dev/null)
|
|
26
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // .new_string // empty' 2>/dev/null)
|
|
27
|
+
|
|
28
|
+
if [ -z "$FILE_PATH" ] || [ -z "$NEW_STRING" ]; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
case "$FILE_PATH" in
|
|
33
|
+
*.css|*.scss|*.tsx|*.jsx|*.ts|*.html|*.vue|*tailwind.config.*|*.tokens.*)
|
|
34
|
+
;;
|
|
35
|
+
*)
|
|
36
|
+
exit 0
|
|
37
|
+
;;
|
|
38
|
+
esac
|
|
39
|
+
|
|
40
|
+
WARNINGS=""
|
|
41
|
+
|
|
42
|
+
# (1) ease-in on UI — must NOT match ease-in-out (which is legitimate).
|
|
43
|
+
# POSIX-grep has no negative lookahead, so we use `ease-in([^-]|$)` which
|
|
44
|
+
# requires any non-hyphen character (or end-of-line) after ease-in.
|
|
45
|
+
if echo "$NEW_STRING" | grep -qE '(transition|animation)[[:space:]]*:[^;]*ease-in([^-]|$)'; then
|
|
46
|
+
WARNINGS+=" • ease-in on UI transition/animation — use ease-out (starts fast, feels responsive)\n"
|
|
47
|
+
elif echo "$NEW_STRING" | grep -qE '(transition-timing-function|animation-timing-function)[[:space:]]*:[[:space:]]*ease-in([^-]|$)'; then
|
|
48
|
+
WARNINGS+=" • ease-in timing function — use ease-out\n"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# (2) transition: all
|
|
52
|
+
if echo "$NEW_STRING" | grep -qE 'transition[[:space:]]*:[[:space:]]*all\b'; then
|
|
53
|
+
WARNINGS+=" • transition: all — specify exact properties (transform/opacity) to avoid layout stutter\n"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Tailwind transition-all
|
|
57
|
+
if echo "$NEW_STRING" | grep -qE '\btransition-all\b'; then
|
|
58
|
+
WARNINGS+=" • Tailwind transition-all — prefer transition-transform / transition-opacity / transition-colors\n"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# (3) scale(0) as entry animation — but not scale(0.X) which is fine
|
|
62
|
+
if echo "$NEW_STRING" | grep -qE '(transform|animation)[^;]*\bscale\([[:space:]]*0[[:space:]]*\)|@keyframes[^}]*\bscale\([[:space:]]*0[[:space:]]*\)'; then
|
|
63
|
+
WARNINGS+=" • scale(0) as animation target — nothing in the real world appears from true zero; use scale(0.95)\n"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Tailwind scale-0 — must not match scale-0.95 or scale-01 etc.
|
|
67
|
+
# `scale-0` followed by anything that is NOT a digit/period/letter, or end-of-line.
|
|
68
|
+
if echo "$NEW_STRING" | grep -qE 'scale-0[^0-9.a-zA-Z]|scale-0$'; then
|
|
69
|
+
WARNINGS+=" • Tailwind scale-0 — prefer scale-95 (or custom tw scale) for entry/exit animations\n"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# (4) Animating layout properties (width/height/top/left/margin) — expensive
|
|
73
|
+
if echo "$NEW_STRING" | grep -qE 'transition[^;]*\b(width|height|top|left|right|bottom|margin(-top|-right|-bottom|-left)?|padding(-top|-right|-bottom|-left)?)\b'; then
|
|
74
|
+
WARNINGS+=" • Transitioning width/height/top/left/margin — use transform + opacity (compositor-accelerated)\n"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if [ -n "$WARNINGS" ]; then
|
|
78
|
+
echo "" >&2
|
|
79
|
+
echo "⚠ UI: motion anti-patterns in ${FILE_PATH}" >&2
|
|
80
|
+
printf "%b" "$WARNINGS" >&2
|
|
81
|
+
echo " See .claude/rules/motion-and-animation.md" >&2
|
|
82
|
+
echo " Opt out: export CLAUDE_DISABLE_UI_ANIM_CHECK=1" >&2
|
|
83
|
+
echo "" >&2
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
exit 0
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ui-banned-fonts-check.sh — warns on reflex-list fonts in .css/.tsx/.html
|
|
3
|
+
# Triggers on: PostToolUse (Edit|Write)
|
|
4
|
+
# Profile: all (advisory only, never blocks)
|
|
5
|
+
# Opt-out: CLAUDE_DISABLE_UI_FONT_CHECK=1
|
|
6
|
+
#
|
|
7
|
+
# Scans the incoming diff for fonts in the reflex_fonts_to_reject list
|
|
8
|
+
# from .claude/rules/ui-anti-patterns.md. Writes a stderr
|
|
9
|
+
# warning pointing at the rule so Claude can correct course BEFORE the
|
|
10
|
+
# edit settles into the design system. Never blocks — exit 0 always.
|
|
11
|
+
|
|
12
|
+
# Unified profile + disable check
|
|
13
|
+
SUPERKIT_PROFILE_LIB="$(dirname "$0")/lib/profile.sh"
|
|
14
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] || SUPERKIT_PROFILE_LIB="$(dirname "$0")/../lib/profile.sh"
|
|
15
|
+
# shellcheck source=/dev/null
|
|
16
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] && source "$SUPERKIT_PROFILE_LIB" && should_skip_hook "$(basename "$0" .sh)" && exit 0
|
|
17
|
+
|
|
18
|
+
if [ "${CLAUDE_DISABLE_UI_FONT_CHECK:-}" = "1" ]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
23
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .file_path // empty' 2>/dev/null)
|
|
24
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // .new_string // empty' 2>/dev/null)
|
|
25
|
+
|
|
26
|
+
if [ -z "$FILE_PATH" ] || [ -z "$NEW_STRING" ]; then
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Only scan UI-relevant files
|
|
31
|
+
case "$FILE_PATH" in
|
|
32
|
+
*.css|*.scss|*.tsx|*.jsx|*.ts|*.html|*.vue|*tailwind.config.*|*.tokens.*)
|
|
33
|
+
;;
|
|
34
|
+
*)
|
|
35
|
+
exit 0
|
|
36
|
+
;;
|
|
37
|
+
esac
|
|
38
|
+
|
|
39
|
+
# Skip if file path suggests we're in a code-block / prose / syntax highlighter
|
|
40
|
+
# context where monospace fonts like Space Mono are legitimately used.
|
|
41
|
+
case "$FILE_PATH" in
|
|
42
|
+
*code-block*|*codeblock*|*prose*|*syntax-highlight*|*highlighter*)
|
|
43
|
+
exit 0
|
|
44
|
+
;;
|
|
45
|
+
esac
|
|
46
|
+
|
|
47
|
+
# reflex_fonts_to_reject — case-insensitive exact-ish matching.
|
|
48
|
+
# Match is scoped to font-family declarations and common Tailwind font classes
|
|
49
|
+
# to avoid false positives (e.g. a variable named `inter` in JSX).
|
|
50
|
+
BANNED_PATTERNS=(
|
|
51
|
+
'Fraunces'
|
|
52
|
+
'Newsreader'
|
|
53
|
+
'\bLora\b'
|
|
54
|
+
'Crimson[[:space:]]*(Pro|Text)?'
|
|
55
|
+
'Playfair([[:space:]]*Display)?'
|
|
56
|
+
'Cormorant([[:space:]]*Garamond)?'
|
|
57
|
+
'\bSyne\b'
|
|
58
|
+
'IBM[[:space:]]*Plex[[:space:]]*(Sans|Serif|Mono)'
|
|
59
|
+
'Space[[:space:]]*(Mono|Grotesk)'
|
|
60
|
+
'\bInter\b'
|
|
61
|
+
'DM[[:space:]]*(Sans|Serif[[:space:]]*(Display|Text))'
|
|
62
|
+
'\bOutfit\b'
|
|
63
|
+
'Plus[[:space:]]*Jakarta[[:space:]]*Sans'
|
|
64
|
+
'Instrument[[:space:]]*(Sans|Serif)'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Collect hits
|
|
68
|
+
HITS=""
|
|
69
|
+
for pat in "${BANNED_PATTERNS[@]}"; do
|
|
70
|
+
# Look for font in font-family declaration OR Tailwind font-* utility OR import url
|
|
71
|
+
matches=$(echo "$NEW_STRING" | grep -E "(font-family:.*${pat}|font-\[['\"]?${pat}|['\"]${pat}['\"].*(font|family)|fonts\.googleapis\.com.*${pat// /+}|${pat}[[:space:]]*[,;])" -io 2>/dev/null | head -3)
|
|
72
|
+
if [ -n "$matches" ]; then
|
|
73
|
+
# Extract clean font name for reporting
|
|
74
|
+
clean=$(echo "$pat" | sed -E 's/\\b|\[\[:space:\]\]\*|\(|\)|\?|\|/ /g' | tr -s ' ' | sed -E 's/^ | $//g' | head -c 40)
|
|
75
|
+
HITS="${HITS} • ${clean}\n"
|
|
76
|
+
fi
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
if [ -n "$HITS" ]; then
|
|
80
|
+
echo "" >&2
|
|
81
|
+
echo "⚠ UI: reflex-list font detected in ${FILE_PATH}" >&2
|
|
82
|
+
printf "%b" "$HITS" >&2
|
|
83
|
+
echo " These fonts are the LLM's training-data defaults and create visual" >&2
|
|
84
|
+
echo " monoculture. Consider running the font-selection procedure in" >&2
|
|
85
|
+
echo " .claude/rules/typography-guidelines.md (Step 1-4)." >&2
|
|
86
|
+
echo " Opt out: export CLAUDE_DISABLE_UI_FONT_CHECK=1" >&2
|
|
87
|
+
echo "" >&2
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
exit 0
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ui-color-check.sh — warns on pure #000/#fff, AI-palette patterns, gradient text
|
|
3
|
+
# Triggers on: PostToolUse (Edit|Write)
|
|
4
|
+
# Profile: all (advisory only, never blocks)
|
|
5
|
+
# Opt-out: CLAUDE_DISABLE_UI_COLOR_CHECK=1
|
|
6
|
+
#
|
|
7
|
+
# Flags three categories of AI-color-reflex:
|
|
8
|
+
# 1. Pure #000 / #fff / rgb(0,0,0) / rgb(255,255,255)
|
|
9
|
+
# 2. Gradient text (background-clip: text with a multi-color gradient)
|
|
10
|
+
# 3. Purple→blue / cyan-on-black / neon-glow accents
|
|
11
|
+
#
|
|
12
|
+
# Per color-and-contrast.md: tint everything toward brand hue, use oklch,
|
|
13
|
+
# avoid gradient text for impact, avoid the AI palette.
|
|
14
|
+
|
|
15
|
+
# Unified profile + disable check
|
|
16
|
+
SUPERKIT_PROFILE_LIB="$(dirname "$0")/lib/profile.sh"
|
|
17
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] || SUPERKIT_PROFILE_LIB="$(dirname "$0")/../lib/profile.sh"
|
|
18
|
+
# shellcheck source=/dev/null
|
|
19
|
+
[ -f "$SUPERKIT_PROFILE_LIB" ] && source "$SUPERKIT_PROFILE_LIB" && should_skip_hook "$(basename "$0" .sh)" && exit 0
|
|
20
|
+
|
|
21
|
+
if [ "${CLAUDE_DISABLE_UI_COLOR_CHECK:-}" = "1" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
26
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .file_path // empty' 2>/dev/null)
|
|
27
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // .new_string // empty' 2>/dev/null)
|
|
28
|
+
|
|
29
|
+
if [ -z "$FILE_PATH" ] || [ -z "$NEW_STRING" ]; then
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Only scan UI-relevant files
|
|
34
|
+
case "$FILE_PATH" in
|
|
35
|
+
*.css|*.scss|*.tsx|*.jsx|*.ts|*.html|*.vue|*tailwind.config.*|*.tokens.*)
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
exit 0
|
|
39
|
+
;;
|
|
40
|
+
esac
|
|
41
|
+
|
|
42
|
+
WARNINGS=""
|
|
43
|
+
|
|
44
|
+
# (1) Pure black / white — look in color / background(-color) / fill / stroke contexts
|
|
45
|
+
# to avoid false positives on shadow opacity, box-shadow: 0 0 0 etc.
|
|
46
|
+
# SEP matches :, optional whitespace, optional quote/backtick (JSX/TS inline styles)
|
|
47
|
+
SEP='[[:space:]]*:[[:space:]]*[\"'"'"'\`]*[[:space:]]*'
|
|
48
|
+
if echo "$NEW_STRING" | grep -qE "(color|background|background-color|fill|stroke)${SEP}#(000|fff|000000|ffffff|FFF|FFFFFF)([^0-9a-fA-F]|$)"; then
|
|
49
|
+
WARNINGS+=" • Pure #000 or #fff in color/background — tint toward brand hue (oklch)\n"
|
|
50
|
+
elif echo "$NEW_STRING" | grep -qE "(color|background|background-color|fill|stroke)${SEP}rgb[a]?\([[:space:]]*0[[:space:]]*,[[:space:]]*0[[:space:]]*,[[:space:]]*0|(color|background|background-color|fill|stroke)${SEP}rgb[a]?\([[:space:]]*255[[:space:]]*,[[:space:]]*255[[:space:]]*,[[:space:]]*255"; then
|
|
51
|
+
WARNINGS+=" • Pure rgb(0,0,0) or rgb(255,255,255) — tint toward brand hue (oklch)\n"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Tailwind bg-black / text-black / bg-white / text-white (not tinted)
|
|
55
|
+
# Note: if the project uses Tailwind with customised black/white tokens, this
|
|
56
|
+
# may false-positive. It's advisory only, so a small false-positive tax is OK.
|
|
57
|
+
if echo "$NEW_STRING" | grep -qE '\b(bg|text|fill|stroke|border)-(black|white)\b'; then
|
|
58
|
+
WARNINGS+=" • Tailwind bg-black/bg-white or text-black/text-white — prefer tinted neutrals\n"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# (2) Gradient text — background-clip: text with a *-gradient background
|
|
62
|
+
if echo "$NEW_STRING" | grep -qE 'background-clip[[:space:]]*:[[:space:]]*text' && \
|
|
63
|
+
echo "$NEW_STRING" | grep -qE 'background(-image)?[[:space:]]*:[[:space:]]*(linear|radial|conic)-gradient'; then
|
|
64
|
+
WARNINGS+=" • Gradient text detected (background-clip: text + gradient) — solid colors only for text\n"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Tailwind gradient-text pattern
|
|
68
|
+
if echo "$NEW_STRING" | grep -qE 'bg-clip-text[[:space:]][^>]*bg-gradient-to|bg-gradient-to[[:space:]][^>]*bg-clip-text'; then
|
|
69
|
+
WARNINGS+=" • Tailwind gradient text (bg-clip-text + bg-gradient-*) — solid colors only for text\n"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# (3) AI palette — purple-to-blue gradient
|
|
73
|
+
if echo "$NEW_STRING" | grep -qiE 'linear-gradient\([^)]*(purple|violet|indigo|#8b5cf6|#a855f7|#7c3aed)[^)]*(blue|cyan|#3b82f6|#06b6d4|#0ea5e9)'; then
|
|
74
|
+
WARNINGS+=" • Purple→blue gradient detected — a trademark AI-palette pattern, reconsider\n"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Cyan on black — #0ff or oklch cyan on pure black
|
|
78
|
+
if echo "$NEW_STRING" | grep -qE 'color[[:space:]]*:[[:space:]]*(#0ff|#00ffff|cyan)' && \
|
|
79
|
+
echo "$NEW_STRING" | grep -qE '(background|bg)[^;]*(#000|#0+0|black)'; then
|
|
80
|
+
WARNINGS+=" • Cyan on black detected — the AI 'cyber' aesthetic default\n"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# No oklch in a file that only uses hsl (suggest migration)
|
|
84
|
+
# Only warn when the file looks like it's defining a palette (multiple color tokens)
|
|
85
|
+
if echo "$NEW_STRING" | grep -qE 'hsl\(' && ! echo "$NEW_STRING" | grep -qE 'oklch\('; then
|
|
86
|
+
# Count actual hsl() occurrences, not lines containing hsl
|
|
87
|
+
hsl_count=$(echo "$NEW_STRING" | grep -oE 'hsl\(' | wc -l | tr -d ' ')
|
|
88
|
+
if [ "${hsl_count:-0}" -ge 3 ]; then
|
|
89
|
+
WARNINGS+=" • Multiple hsl() declarations without oklch() — prefer oklch for perceptual uniformity\n"
|
|
90
|
+
fi
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
if [ -n "$WARNINGS" ]; then
|
|
94
|
+
echo "" >&2
|
|
95
|
+
echo "⚠ UI: color anti-patterns in ${FILE_PATH}" >&2
|
|
96
|
+
printf "%b" "$WARNINGS" >&2
|
|
97
|
+
echo " See .claude/rules/color-and-contrast.md and ui-anti-patterns.md" >&2
|
|
98
|
+
echo " Opt out: export CLAUDE_DISABLE_UI_COLOR_CHECK=1" >&2
|
|
99
|
+
echo "" >&2
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
exit 0
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: color-and-contrast
|
|
3
|
+
description: "Color system rules — OKLCH over HSL, tinted neutrals, 60-30-10 weight, contrast, dark/light theme selection by use context. Auto-loaded when editing UI files."
|
|
4
|
+
tokens: 2498
|
|
5
|
+
alwaysApply: false
|
|
6
|
+
applyWhenPaths:
|
|
7
|
+
- "**/*.tsx"
|
|
8
|
+
- "**/*.jsx"
|
|
9
|
+
- "**/*.ts"
|
|
10
|
+
- "**/*.css"
|
|
11
|
+
- "**/*.scss"
|
|
12
|
+
- "**/*.html"
|
|
13
|
+
- "**/*.vue"
|
|
14
|
+
- "**/tailwind.config.*"
|
|
15
|
+
- "**/*.tokens.*"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Color & Contrast
|
|
19
|
+
|
|
20
|
+
## Principles (always apply)
|
|
21
|
+
|
|
22
|
+
1. **Use OKLCH, not HSL.** OKLCH is perceptually uniform — equal steps
|
|
23
|
+
in lightness *look* equal, which HSL does not deliver. Modern browsers
|
|
24
|
+
all support `oklch()`; there is no reason to ship HSL in new code.
|
|
25
|
+
2. **Reduce chroma at the extremes of lightness.** High chroma at 90%+
|
|
26
|
+
lightness or below 15% lightness reads as garish or muddy. A light
|
|
27
|
+
blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base
|
|
28
|
+
color. Similarly for deep shades — a near-black surface wants
|
|
29
|
+
~0.02 chroma, not 0.15.
|
|
30
|
+
3. **Tint your neutrals toward the brand hue.** Even a chroma of
|
|
31
|
+
0.005–0.01 is perceptible and creates subconscious cohesion between
|
|
32
|
+
brand color and UI surfaces. Pure neutrals feel disconnected.
|
|
33
|
+
4. **60-30-10 is about visual weight, not pixel count.** 60% neutrals
|
|
34
|
+
and surfaces, 30% secondary text and borders, 10% accent. The accent
|
|
35
|
+
works *because* it is rare; overuse destroys its power.
|
|
36
|
+
5. **No pure black or pure white.** `#000` and `#fff` never appear in
|
|
37
|
+
nature. Always tint. A "near-black" surface at `oklch(15% 0.01 260)`
|
|
38
|
+
is categorically different from `#000` even though the difference is
|
|
39
|
+
subtle on first glance.
|
|
40
|
+
|
|
41
|
+
## Theme selection — by USE context
|
|
42
|
+
|
|
43
|
+
Theme (light vs dark) is DERIVED from the audience and physical viewing
|
|
44
|
+
context, not picked from a default. Read the brief and ask: when is this
|
|
45
|
+
product used, by whom, in what physical setting?
|
|
46
|
+
|
|
47
|
+
| Product | Theme | Reasoning |
|
|
48
|
+
|---------|-------|-----------|
|
|
49
|
+
| Perp DEX consumed during fast trading sessions | Dark | Reduces eye strain over long sessions; trading rooms often dim. |
|
|
50
|
+
| Hospital portal consumed by anxious patients on phones late at night | Light | Bright environment perception = trust/safety; dark feels ominous in healthcare. |
|
|
51
|
+
| Children's reading app | Light | Parents view dark interfaces as "less safe for kids"; content needs to feel open. |
|
|
52
|
+
| Vintage motorcycle forum (users in their garage at 9pm) | Dark | Matches the physical environment and enthusiast subculture. |
|
|
53
|
+
| Observability dashboard for SREs in dark rooms | Dark | Physical environment match; graph contrast against dark is clearer. |
|
|
54
|
+
| Wedding planning checklist on Sunday morning | Light | Bright/optimistic mood; physical environment bright. |
|
|
55
|
+
| Music player for headphone listening at night | Dark | Cinematic; physical environment dark. |
|
|
56
|
+
| Food magazine homepage browsed over coffee | Light | Food imagery reads as more appetising on light surfaces. |
|
|
57
|
+
|
|
58
|
+
**Do not default to light "to play it safe." Do not default to dark "to
|
|
59
|
+
look cool."** Both defaults are the lazy reflex. The correct theme is
|
|
60
|
+
the one the actual user wants in their actual context.
|
|
61
|
+
|
|
62
|
+
If neither dark nor light is obviously right, ship **light with a
|
|
63
|
+
high-quality dark mode**. (Not the other way around — light-first
|
|
64
|
+
designs tend to port to dark cleanly; dark-first designs often have
|
|
65
|
+
contrast issues in their light port.)
|
|
66
|
+
|
|
67
|
+
## Building the palette
|
|
68
|
+
|
|
69
|
+
### Step 1 — Pick the brand hue first
|
|
70
|
+
|
|
71
|
+
Every other decision follows from one anchor color. This is usually the
|
|
72
|
+
brand's actual hue (existing logo, product identity). If truly
|
|
73
|
+
greenfield, pick based on the three-word brief from
|
|
74
|
+
`typography-guidelines.md`:
|
|
75
|
+
|
|
76
|
+
- "warm, mechanical, opinionated" → oklch hue 30–60 (orange/brown)
|
|
77
|
+
- "calm, clinical, careful" → oklch hue 200–240 (cool blue-green)
|
|
78
|
+
- "expensive, quiet, precise" → oklch hue 20–40 with very low chroma
|
|
79
|
+
- "fast, dense, unimpressed" → oklch hue 120–160 with moderate chroma
|
|
80
|
+
(mint/green) or a desaturated near-grey
|
|
81
|
+
|
|
82
|
+
### Step 2 — Build neutrals tinted toward the brand hue
|
|
83
|
+
|
|
84
|
+
```css
|
|
85
|
+
--neutral-0: oklch(98% 0.005 <hue>); /* page */
|
|
86
|
+
--neutral-10: oklch(94% 0.008 <hue>); /* subtle surface */
|
|
87
|
+
--neutral-20: oklch(88% 0.010 <hue>); /* hairline border */
|
|
88
|
+
--neutral-40: oklch(68% 0.012 <hue>); /* placeholder / muted icon */
|
|
89
|
+
--neutral-60: oklch(50% 0.015 <hue>); /* secondary text */
|
|
90
|
+
--neutral-80: oklch(30% 0.018 <hue>); /* body text */
|
|
91
|
+
--neutral-95: oklch(15% 0.010 <hue>); /* max-contrast text / deep surface */
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Note: chroma INCREASES slightly into the middle of the scale and
|
|
95
|
+
DECREASES at both extremes. This matches perception.
|
|
96
|
+
|
|
97
|
+
### Step 3 — Accent scale with reduced chroma at extremes
|
|
98
|
+
|
|
99
|
+
```css
|
|
100
|
+
--accent-50: oklch(95% 0.05 <hue>);
|
|
101
|
+
--accent-300: oklch(78% 0.12 <hue>);
|
|
102
|
+
--accent-500: oklch(60% 0.18 <hue>); /* base brand color */
|
|
103
|
+
--accent-700: oklch(42% 0.14 <hue>);
|
|
104
|
+
--accent-900: oklch(22% 0.08 <hue>);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Compare chromas: `0.05 → 0.12 → 0.18 → 0.14 → 0.08`. The peak is in the
|
|
108
|
+
middle, not at either end. A 500 color at chroma 0.18 would be
|
|
109
|
+
overbearing at 900 lightness.
|
|
110
|
+
|
|
111
|
+
### Step 4 — Status colors, but treat them as system, not brand
|
|
112
|
+
|
|
113
|
+
Success, warning, error, info — these should NOT be your brand color
|
|
114
|
+
with a hue shift. They should be their own mini-palettes. An e-commerce
|
|
115
|
+
brand at hue 40 (orange) cannot use its accent 500 as a warning color —
|
|
116
|
+
there is no differentiation between brand and warning.
|
|
117
|
+
|
|
118
|
+
Use hue 140 (green) for success, hue 60–80 for warning, hue 25 (red-orange)
|
|
119
|
+
for error, hue 250 (blue) for info. Apply the same lightness/chroma
|
|
120
|
+
scaling as the accent scale.
|
|
121
|
+
|
|
122
|
+
## Contrast and accessibility
|
|
123
|
+
|
|
124
|
+
- **Metric selection is deterministic — no judgment call.** WCAG AA is
|
|
125
|
+
the hard floor in every project: ≥ 4.5:1 for body text, ≥ 3:1 for
|
|
126
|
+
large text (18px+ or 14px+ bold). Additionally check APCA targets
|
|
127
|
+
(Lc ≥ 60 body, Lc ≥ 45 large — APCA correlates better with
|
|
128
|
+
readability) ONLY when the project already ships APCA tooling
|
|
129
|
+
(search `package.json` and lockfile for "apca"). No APCA tooling
|
|
130
|
+
found → check WCAG only; do not guess Lc values.
|
|
131
|
+
- **Do NOT use gray text on colored backgrounds.** Gray on a colored
|
|
132
|
+
surface reads as washed out. Instead, use a shade of the background
|
|
133
|
+
color — for an accent-tinted card, the body text should be a deep
|
|
134
|
+
shade of the same hue, not neutral gray.
|
|
135
|
+
- **Borders:** a 1px border at `neutral-20` on a `neutral-0` background
|
|
136
|
+
is the right starting point. If you need more separation, prefer a
|
|
137
|
+
slight shadow over a heavier border.
|
|
138
|
+
- **Focus rings:** 2px minimum, contrast ≥3:1 against both the element
|
|
139
|
+
and the background. Don't rely on default browser rings; they hide on
|
|
140
|
+
colored surfaces.
|
|
141
|
+
|
|
142
|
+
## Modern CSS color tools
|
|
143
|
+
|
|
144
|
+
All supported in every modern browser — use them in new code.
|
|
145
|
+
|
|
146
|
+
```css
|
|
147
|
+
/* Perceptually uniform lightness scale */
|
|
148
|
+
--surface: oklch(from var(--brand) 98% c h);
|
|
149
|
+
|
|
150
|
+
/* Mix between brand and neutral for hover states */
|
|
151
|
+
--brand-hover: color-mix(in oklch, var(--brand) 92%, black);
|
|
152
|
+
|
|
153
|
+
/* Auto light/dark */
|
|
154
|
+
color: light-dark(var(--neutral-80), var(--neutral-0));
|
|
155
|
+
background: light-dark(var(--neutral-0), var(--neutral-95));
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Color rules of execution
|
|
159
|
+
|
|
160
|
+
**DO:**
|
|
161
|
+
- Use `oklch()` everywhere. HSL in new code is tech debt.
|
|
162
|
+
- Tint your neutrals toward the brand hue. Check by viewing them beside
|
|
163
|
+
pure gray — if they don't look different, increase chroma by 0.002.
|
|
164
|
+
- Use `color-mix()` for hover/pressed states instead of hand-picked shades.
|
|
165
|
+
- Use `light-dark()` for theme-aware colors; it is simpler than dual
|
|
166
|
+
CSS variable sets.
|
|
167
|
+
- Pick a theme based on use context; document the reasoning in one line
|
|
168
|
+
at the top of the palette file.
|
|
169
|
+
|
|
170
|
+
**DO NOT:**
|
|
171
|
+
- Use HSL for new palettes. (OK for small legacy patches, not for new
|
|
172
|
+
systems.)
|
|
173
|
+
- Use pure `#000` / `#fff` / `rgb(0,0,0)` anywhere.
|
|
174
|
+
- Use gray text on a colored background. Tint the text.
|
|
175
|
+
- Ship the AI palette: cyan-on-dark, purple-to-blue gradient text,
|
|
176
|
+
neon accents on a black page.
|
|
177
|
+
- Use gradient text for impact. Solid colors for text; see
|
|
178
|
+
`ui-anti-patterns.md` for the strict definition.
|
|
179
|
+
- Default to dark mode with glowing accents "because it looks cool."
|
|
180
|
+
- Default to light mode "to play it safe."
|
|
181
|
+
- Use the same accent color for brand and for system colors (success,
|
|
182
|
+
warning, error).
|
|
183
|
+
|
|
184
|
+
## Validation procedure (before shipping a palette)
|
|
185
|
+
|
|
186
|
+
Pick the branch with one test: can you render CSS and view the result
|
|
187
|
+
this session (browser, Playwright, screenshot tooling)? Yes → Branch A.
|
|
188
|
+
No, or unsure → Branch B. Never claim a render or simulator run that
|
|
189
|
+
did not happen.
|
|
190
|
+
|
|
191
|
+
**Branch A — rendering available:**
|
|
192
|
+
|
|
193
|
+
1. Render the full neutral scale beside `#808080`. If any step looks
|
|
194
|
+
identical to pure gray, increase its chroma by 0.002.
|
|
195
|
+
2. Render accent-500 on neutral-0 and on neutral-95, and compute its
|
|
196
|
+
WCAG contrast against both. Below 3:1 on either surface → adjust
|
|
197
|
+
accent-500 lightness until both pass.
|
|
198
|
+
3. Run the palette through a deuteranopia / protanopia simulator
|
|
199
|
+
(e.g., Sim Daltonism, Stark). If status colors collapse onto each
|
|
200
|
+
other, re-hue them.
|
|
201
|
+
4. Check text on every background used — minimum 4.5:1 for body,
|
|
202
|
+
3:1 for large.
|
|
203
|
+
|
|
204
|
+
**Branch B — no rendering (the normal editing session).** Validate
|
|
205
|
+
numerically from the token values:
|
|
206
|
+
|
|
207
|
+
1. Read every neutral token: chroma ≥ 0.005 and one consistent hue
|
|
208
|
+
angle across the scale. Any step at chroma 0 → retint it (add
|
|
209
|
+
0.002 minimum).
|
|
210
|
+
2. Compute the WCAG ratio for every text-on-background pair with a
|
|
211
|
+
Bash `python3`/`node` one-liner: linearize each sRGB channel
|
|
212
|
+
(c/12.92 if c ≤ 0.03928, else ((c+0.055)/1.055)^2.4); relative
|
|
213
|
+
luminance L = 0.2126R + 0.7152G + 0.0722B; ratio =
|
|
214
|
+
(L_lighter + 0.05) / (L_darker + 0.05). Concrete hex/rgb pairs give
|
|
215
|
+
an exact ratio; an oklch value or unresolved `var()` chain you
|
|
216
|
+
cannot convert → estimate from the lightness difference and label
|
|
217
|
+
the number "estimated".
|
|
218
|
+
3. Status colors: no simulator ran, so hue alone must not carry
|
|
219
|
+
meaning — every status indicator pairs color with an icon or text
|
|
220
|
+
label, or adjacent status colors differ by ≥ 15 lightness points.
|
|
221
|
+
4. Report each check as VERIFIED (with the computed numbers) or
|
|
222
|
+
NOT RUN — in this branch the render and simulator checks are always
|
|
223
|
+
NOT RUN; say so explicitly. An estimated (not exactly computed)
|
|
224
|
+
value caps that check's confidence at MEDIUM — the same rule
|
|
225
|
+
`ui-color-reviewer` applies to contrast findings.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
Attribution: adapted from Impeccable's `reference/color-and-contrast.md`
|
|
230
|
+
(Apache-2.0). See `../NOTICE.md`.
|