persist_design_system crashed with AttributeError: 'NoneType' object has
no attribute 'lower' when the design_system dict carries an explicit
project_name of None (the default of generate(query, project_name=None)).
dict.get("project_name", "default") only substitutes the default for a
MISSING key, not a present-but-None value, so project_name.lower() blew
up.
Coalesce falsy values (None/""/missing) to "default" before slugifying.
Applied to both the source of truth and the bundled cli/assets copy.
The "search blindness" half of #159 (core.py tokenize length filter) is
already resolved on main (`len(w) >= 2`), so this targets the remaining
crash only.
Closes#159
Co-authored-by: YangKuoshih <155388493+YangKuoshih@users.noreply.github.com>
On Windows, an older install (or a git checkout that materialized the
repo's symlinked data/scripts as plain "pointer" files) leaves a regular
file at <skill>/data or <skill>/scripts. copyDataAndScripts then calls
mkdir on that path, which throws EEXIST; under `uipro init --ai all` the
per-platform error is swallowed, leaving e.g. codex with the stale
pointer files and no real directories.
Add ensureCleanDir(): before mkdir, lstat the target and remove it if it
is not already a directory. Existing real directories are preserved
(re-install is unaffected). Verified with a repro harness.
Closes#237
* fix CLI asset sync
* fix(cli): normalize line endings in asset sync/check
check:assets hashed raw bytes, so identical CSV/JSON/py content with
CRLF vs LF (git autocrlf on checkout) was reported as stale drift,
blocking the release guard on Windows/mixed checkouts.
- fileHash now normalizes CRLF->LF before hashing, so check:assets
compares content, not line endings.
- sync:assets writes LF-normalized copies instead of a raw byte copy,
so re-syncing is deterministic across platforms.
All synced assets are text (csv/json/md/py); no binaries affected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* ci: enforce CLI asset sync on PRs
Adds a Check asset sync workflow that runs `npm run check:assets` on any
PR touching src/ui-ux-pro-max/** or cli/assets/**, so the bundled CLI
assets can't silently drift from the source of truth.
The check uses only node builtins (no install step) and normalizes
line endings before hashing, so it hard-fails on real content drift
without the CRLF/LF soft-fail hack other approaches needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix: V-001 security vulnerability
Automated security fix generated by Orbis Security AI
* feat(cli): add optional GitHub token support with proper UX and docs
- Rename env var from GITHUB_TOKEN to UI_PRO_MAX_GITHUB_TOKEN (primary),
with GITHUB_TOKEN as fallback — avoids silently attaching CI workflow
credentials that GitHub Actions injects automatically
- Add whitespace trim guard to prevent malformed Authorization headers
- Add getGitHubTokenGuidance() helper exported from github.ts so rate-limit
errors and spinner warnings tell users exactly how to fix the problem
- Thread optional token param through fetchReleases, getLatestRelease,
downloadRelease signatures
- Add --token flag to init, versions, update commands (Commander.js wiring)
- Update rate-limit catch in tryGitHubInstall to show token guidance
- Document token options (flag, env var, fallback) in cli/README.md with
CI warning about GITHUB_TOKEN scope
Supersedes the narrower env-only approach in PR #294 and incorporates the
safeguards requested during review of closed PR #186.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The Agent Skills spec requires names to match [a-z0-9-] only.
The colon in 'ckm:' prefix causes daily validation errors:
name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)
This affects all six ckm-prefixed skills. Replace ':' with '-'.
Co-authored-by: Thomas Schneider <tho.schneider@sap.com>
* fix: bump skill.json version to 2.6.2
* fix: bump marketplace.json and plugin.json version to 2.6.2
---------
Co-authored-by: shipengqi <pooky.shi@gamil.com>
Add html.escape() to all 46 user-controlled data.get() calls across
all 7 slide generator functions (title, problem, solution, metrics,
chart, testimonial, cta) and the deck title.
Add URL scheme validation for cta_url href to block javascript: URI
injection.
Closes#247
The _format_plugins() method interpolated plugin names directly into
require() statements without sanitization. A plugin name containing
a single quote could break out of require() and inject arbitrary
JavaScript that executes when Node.js loads the generated config.
Add a strict regex allowlist matching valid npm package name patterns
(optional @scope, alphanumeric/hyphen/underscore, optional subpath).
Reject any plugin name that doesn't match before generating output.
Closes#246
Breaking changes fixed:
- Row 8/9: icon format corrected from 'lucide:home' (v3) to 'i-lucide-home' (v4 Iconify i-prefix)
- Row 18: useOverlay API updated from .open(Component, {props}) to .create(Component).open({props})
New v4 guidelines added (rows 51-70):
- Auto-registered modules: do not re-add @nuxt/icon @nuxt/fonts @nuxtjs/color-mode
- Official nuxi init templates for project bootstrapping
- Local Iconify JSON install for SSR reliability
- Global icon overrides via appConfig.ui.icons
- New form components: UFileUpload, UInputDate, UInputTags, UColorPicker
- New data components: UTree, UMarquee
- UContextMenu for right-click menus
- Awaiting overlay result Promise for confirmation dialogs
- UCommandPalette grouped items and extractShortcuts
- UHeader/UFooter/UPageAside layout components
- ClientOnly pattern for color mode hydration safety
- Generated theme file (.nuxt/ui/) for slot discovery
- defineShortcuts whenever condition guard
- UApp locale prop for i18n (50+ built-in locales)
Sync cli/assets to match src.
execSync with a backtick template string creates a shell-expansion
surface. Although all three variables (generateScript, DESIGN_TOKENS_JSON,
DESIGN_TOKENS_CSS) are currently hardcoded constants, the pattern is
fragile — any future substitution of user-controlled data would create
shell injection.
Replace with execFileSync('node', [...args]) to eliminate the shell
entirely and make the boundary explicit.
Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
All three are in the canonical src/ tree, reproduced on Python 3.14.5:
1. data/typography.csv — all 73 'Google Fonts URL' values were unusable
fonts.google.com/share *UI* links, not stylesheet hrefs. Replaced with the
proper fonts.googleapis.com/css2 URLs (extracted verbatim from each row's
correct 'CSS Import' column), so the URL column is actually loadable.
2. scripts/core.py — BM25 tokenizer kept only words >2 chars, so common design
terms 'ux', 'ui', 'ai', '3d' tokenized to nothing and returned 0 results
(e.g. `--domain style "3d"`). Changed >2 to >=2; '3d'/'ai' now match.
3. scripts/search.py — `--persist` without `-p` printed
'design-system/default/' but actually wrote to the query slug
(e.g. design-system/fintech-crypto/). Use the same default the writer uses
so the printed path matches reality.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add cross-platform Python command note to skills and docs:
- CLAUDE.md: Add Windows note in Prerequisites
- ui-ux-pro-max/SKILL.md: Add Windows note in Prerequisites
- design/SKILL.md: Add Prerequisites section with Windows note
- banner-design/SKILL.md: Add Prerequisites section with Windows note
- templates/base/skill-content.md: Add Windows note (source template)
Windows uses 'python' instead of 'python3' to run scripts.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Line 14 contained a raw `<args>$ARGUMENTS</args>` tag that was never
replaced during skill generation. This literal XML-like string renders
as part of the skill body and can confuse LLM consumers.
Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
OpenClaw (https://openclaw.ai) is an open-source agent gateway that
runs Claude as its primary backend. This skill works out-of-the-box
inside OpenClaw agents — same SKILL.md + python3 search.py invocation
pattern as the other supported platforms. Adding it to the list so
the install flow can target it.
Co-authored-by: yinhaoti <yinhaoti@macmini.home>
The --force option was accepted by Commander but ignored: writeFile()
always overwrote existing files silently. Users expecting protection
against accidental overwrites had no way to preserve existing configs.
- generatePlatformFiles: check file existence before writing; skip with
a clear message when file exists and force=false
- generateAllPlatformFiles / templateInstall: propagate force parameter
- initCommand: pass options.force through to templateInstall
Behavior change:
uipro init --ai claude → skips if SKILL.md already exists
uipro init --ai claude --force → overwrites regardless
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Both files were stuck at v2.2.1 while plugin.json, skill.json and
cli/package.json had moved to v2.5.0. Claude marketplace reads
marketplace.json for version and palette count — the stale entry
showed outdated data (96 palettes vs actual 161, 13 stacks vs 15).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Merged STACK_CONFIG: kept main's full stack list + added angular & laravel from PR
- Updated platform templates: 161 palettes, 16 stacks across all descriptions
- Listed all 16 stacks in claude.json frontmatter description
- Warn when --global and --legacy are used together (init.ts)
- Update metadata across all platform templates (161 palettes, 15 stacks)
- Bump skill.json version from 2.0.0 to 2.5.0
- Re-throw non-ENOENT errors in uninstall.ts removeSkillDir
- Hoist detectAIType call to avoid double invocation in uninstall
- Add clarifying comment for .shared in AI_FOLDERS mapping
Align npm package version with GitHub release v2.5.0.
All 16 AI types (including trae, opencode, droid, continue,
codebuddy) are now available after npm publish.
Closes#199, #195, #172, #132
Antigravity now defaults to .agents/skills/ directory. Update
AI_FOLDERS mapping and detection logic with backward compat
for existing .agent/ directories.
Closes#196
Add required name and description frontmatter to windsurf, kiro,
cursor, copilot, and roocode platform templates. Update agent.json
frontmatter with current capability counts.
Closes#204, #188, #43
Upgrade the design system terminal output from basic ASCII to Unicode box-drawing characters,
add ANSI true color swatches with graceful fallback, expand the color palette from 5 to 10
colors (Primary, On Primary, Secondary, Accent, Background, Foreground, Muted, Border,
Destructive, Ring) with CSS variable names, and surface Light/Dark mode support from styles.csv.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>