feat(siren): add skills symlink support

Skills are directories (containing SKILL.md) rather than flat files,
so this adds dedicated _add_skill_symlinks() and _cleanup_stale_skills()
functions mirroring the existing command symlink pattern. Only symlinks
pointing into our source tree are managed; skills from other sources
(e.g. ~/.agents/skills/) are left untouched.

Also adds the frontend-design-systems skill for systematic visual
design consistency rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 19:19:21 +00:00
parent 7c30b6c405
commit 015ad895b4
2 changed files with 206 additions and 1 deletions

View File

@@ -0,0 +1,139 @@
---
name: Frontend Design Systems
description: >-
This skill should be used when the user asks to "build a design system",
"create consistent UI", "define color ratios", "set up typography system",
"normalize geometry tokens", "validate visual hierarchy", "apply design
constraints", or when generating frontend UI that requires systematic
visual consistency. Augments the frontend-design skill with system-level
visual decision rules for consistency, hierarchy, and scalable UI
decision-making.
version: 0.1.0
inspired_by: https://www.youtube.com/watch?v=eVnQFWGDEdY
---
# Frontend Design Systems
## Purpose
Augment the `frontend-design` skill with system-level visual decision rules
derived from practical graphic design heuristics. Focus on consistency,
hierarchy, and scalable UI decision-making rather than aesthetic
experimentation.
Apply this skill *after* layout, accessibility, and interaction logic are
established by `frontend-design`.
## Core Principle
Design quality emerges from repeatable systems: ratios, constraints, typography
systems, geometry rules, and hierarchy validation.
Prefer deterministic structure over stylistic improvisation.
## Heuristics
### 1. Color Ratio System
Do not distribute colors evenly. Use proportional dominance:
- 70-90% neutral base
- 10-25% supporting color
- 1-8% accent color
Map accent color to: primary actions, alerts, focus states, brand signals. If
accent overuse occurs, reduce until hierarchy is restored.
### 2. Typography Superfamily Strategy
Default to a Single System: One Family, multiple Weights, Limited Width/Style
Variation.
Express hierarchy via: size, weight, spacing, rhythm.
Introduce additional typefaces only when semantic separation is required (e.g.,
code vs marketing content).
### 3. Geometry Consistency Rule
All UI must inherit a shared structural language: border radius, angle logic,
stroke thickness, elevation system, spacing cadence.
Do not introduce new geometry tokens unless:
- Existing tokens cannot express the requirement
- Functional clarity would otherwise degrade
Consistency > variety.
### 4. Dual-Scale Validation
Evaluate every interface at two levels:
**Macro (~10% scale):** Hierarchy clarity, scanning flow, section priority.
**Micro (~200-300% scale):** Spacing, alignment, typography precision, component
polish.
Reject designs that succeed at only one scale.
### 5. Constraint-First Brand Framing
Before generating UI styles, define negative constraints. Example:
- not playful
- not aggressive
- not corporate
- not experimental
- not premium
- not youthful
Use constraints to filter: color choices, typography decisions, motion styles,
component density. If a design decision conflicts with constraints, discard it.
### 6. Non-Designer Reality Bias
Assume users: are distracted, scroll quickly, use mobile, operate under low
brightness, do not analyze details.
Optimize for: instant comprehension, strong primary action visibility, minimal
cognitive load, clear visual hierarchy within <2 seconds.
Design for use, not inspection.
### 7. Repetition over Novelty
When uncertain: repeat existing visual rules, reinforce hierarchy, reduce
variation.
Allow novelty only after: clarity is achieved, hierarchy is stable, interaction
affordances are obvious.
## Integration Behavior
When layered after `frontend-design`:
1. Convert layout decisions into visual systems: derive color ratios, apply
typography hierarchy, normalize geometry tokens.
2. Run constraint filtering before rendering UI variants.
3. Evaluate macro structure first, micro polish second.
4. Optimize for comprehension speed over stylistic uniqueness.
5. Prefer consistency, predictability, clarity, and restraint over visual
experimentation.
## Failure Modes to Avoid
- Evenly distributed color usage
- Mixing multiple unrelated typefaces
- Inconsistent border radii and spacing logic
- Hierarchy visible only at high zoom
- Designing for designers instead of users
- Novelty introduced without structural justification
## Output Expectations
UI generated with this skill should feel: intentional, cohesive, restrained,
hierarchy-driven, fast to parse, and visually consistent across components and
pages.
Bias toward clarity and repetition until interaction goals are fully satisfied.

68
siren
View File

@@ -49,6 +49,7 @@ define_settings() {
STATIC_SYMLINKS["claude/settings.json"]="${HOME}/.claude/settings.json"
STATIC_SYMLINKS["claude/statusline.sh"]="${HOME}/.claude/statusline.sh"
_add_command_symlinks "claude" "${HOME}/.claude"
_add_skill_symlinks "claude" "${HOME}/.claude"
fi
# Conditionally add symlinks for Cursor.
@@ -444,6 +445,32 @@ _add_command_symlinks() {
done
}
# Add symlinks for all skill directories (containing SKILL.md) in a skills
# directory.
# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude)
_add_skill_symlinks() {
local source_subdir="$1"
local target_base="$2"
local skills_dir="${SCRIPT_DIR}/${source_subdir}/skills"
if [[ ! -d "${skills_dir}" ]]; then
return
fi
local skill_dir
for skill_dir in "${skills_dir}"/*/; do
# Skip if glob didn't match anything (returns literal pattern).
[[ -d "${skill_dir}" ]] || continue
# Only treat directories containing SKILL.md as skills.
if [[ -f "${skill_dir}/SKILL.md" ]]; then
local skill_name
skill_name="$(basename "${skill_dir}")"
STATIC_SYMLINKS["${source_subdir}/skills/${skill_name}"]="${target_base}/skills/${skill_name}"
fi
done
}
# Remove stale symlinks in a commands directory that point to source files that
# no longer exist.
# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude)
@@ -481,6 +508,44 @@ _cleanup_stale_commands() {
done
}
# Remove stale symlinks in a skills directory that point to source
# directories that no longer exist. Only touches symlinks pointing into our
# source tree; symlinks managed by other tools are left untouched.
# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude)
_cleanup_stale_skills() {
local source_subdir="$1"
local target_base="$2"
local skills_dir="${target_base}/skills"
local source_dir="${SCRIPT_DIR}/${source_subdir}/skills"
if [[ ! -d "${skills_dir}" ]]; then
return
fi
local link
for link in "${skills_dir}"/*; do
# Skip if glob didn't match anything (returns literal pattern).
[[ -e "${link}" || -L "${link}" ]] || continue
# Skip if not a symlink.
if [[ ! -L "${link}" ]]; then
continue
fi
local target
target="$(readlink "${link}")"
# Check if the symlink points to our source directory.
if [[ "${target}" == "${source_dir}/"* ]]; then
# If the target directory no longer exists, remove the symlink.
if [[ ! -e "${target}" ]]; then
info "Removing stale symlink: ${link}"
rm -f "${link}"
fi
fi
done
}
# Find the editor CLI command.
#
# Returns: Editor command path via `STDOUT`.
@@ -1277,9 +1342,10 @@ do_config() {
symlink_editor_config
symlink_static_config
# Clean up stale command symlinks.
# Clean up stale command and skill symlinks.
if command -v claude &>/dev/null; then
_cleanup_stale_commands "claude" "${HOME}/.claude"
_cleanup_stale_skills "claude" "${HOME}/.claude"
fi
if [[ "${SETUP_EDITOR}" == "cursor" ]]; then
_cleanup_stale_commands "cursor" "${HOME}/.cursor"