Skip to content

Commit 9ce7c30

Browse files
committed
Add blog post on resolving Claude Code skill path mismatch with npx install
This post explains the issue where skills installed via `npx skill install` are not recognized by Claude Code due to differing directory paths. It provides two solutions: creating a manual symlink for skills and setting up a SessionStart hook for automatic synchronization. The article includes detailed instructions and code snippets for both methods.
1 parent bf86b3c commit 9ce7c30

File tree

4 files changed

+561
-80
lines changed

4 files changed

+561
-80
lines changed

.claude/skills/layer5-blog-writer/SKILL.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,14 @@ python3 "<skill_dir>/scripts/generate_hero_image.py" \
9797

9898
Produces a fully SVG-native 1200x630 image that:
9999

100-
- Generates a **full-canvas freeform gradient background** using the complete Layer5 brand palette: Eerie Black (#1E2117), Charcoal (#3C494F), Steel Teal (#477E96), Keppel/Teal (#00B39F), Caribbean Green (#00D3A9), Saffron (#EBC017), Banana Mania (#FFF3C5)
101-
- Uses 7 overlapping colored ellipses, each heavily Gaussian-blurred (stdDeviation ~120px on a 1200px canvas), composited without symmetry - mimicking the Freeform Gradient tool in Adobe Illustrator
102-
- Selects a composition preset by `--category`: **Corner Warmth** (gold upper-left, teal right, dark lower-left, off-white subject halo where Five stands) or **Deep Space** (dark dominant, luminous central clearing)
103-
- Overlays a real Five mascot SVG at ~95% image height (large, prominent) from a curated set of standalone poses
100+
- Generates a **multi-stop gradient background** matching Layer5's official illustration technique (extracted from Artboard 1.svg and chs-2-intro.svg reference files). Uses overlapping full-canvas rectangles with 10-16 stop linear/radial gradients and `stop-opacity` for compositing - NOT blurred ellipses.
101+
- The signature Layer5 gradient ramp has 16 stops transitioning from Dark Jungle Green (#1E2117) through Charcoal (#3C494F), six intermediate blue-greens (#375154, #305D5D, #266E6A, #1A847B, #0B9E8F), Keppel (#00B39F), to Caribbean Green (#00D3A9). Equivalent ramps exist for Saffron and Steel Teal. These intermediate colors create the rich, deep transitions characteristic of Layer5 illustrations.
102+
- Full brand palette: Eerie Black (#1E2117), Charcoal (#3C494F), Steel Teal (#477E96), Keppel (#00B39F), Caribbean Green (#00D3A9), Saffron (#EBC017), Banana Mania (#FFF3C5)
103+
- White clearing uses the exact radial gradient from chs-2-intro.svg: white at center through #F7FCFC, #E2F6F4, #BFEBE7, #8FDDD4, #52CBBE, #12B8A6 to Keppel at edge
104+
- Selects a composition preset by `--category`:
105+
- **Corner Warmth** (daytime): Saffron upper-left sun, Keppel/Caribbean Green at right edge and bottom, Dark Jungle Green base at lower-left, massive white clearing center-right. NO Steel Teal or Charcoal. Reference: "4000 members", "Recognition Program", "layer5-hero.webp"
106+
- **Deep Space** (night): Steel Teal dominates upper sky, Charcoal at lower corners with extra diagonal darkness, Saffron warm star upper-right, tighter white clearing. Reference: "Meet Five", "Adventures of Five Vol 2" cover
107+
- Overlays a real Five mascot SVG at ~95% image height (large, prominent) from a curated set of 10 standalone poses
104108
- Embeds Qanelas Soft font (from `static/fonts/qanelas-soft/`) for brand-accurate typography
105109
- Adds an off-center white/off-white glow close behind Five so the black skeleton reads clearly - this is NOT a centered radial spotlight
106110

.claude/skills/layer5-blog-writer/scripts/generate_hero_image.py

Lines changed: 250 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -56,65 +56,207 @@
5656
SUBTITLE_HEX = "#C8DDD9" # near-white with a slight teal tint — readable on dark scrim
5757

5858

59-
# ── Freeform Background Compositions ──────────────────────────────────────
59+
# ── Multi-Stop Gradient Background ────────────────────────────────────────
6060
#
61-
# Each composition is a list of blob descriptors:
62-
# (cx_frac, cy_frac, rx_frac, ry_frac, color, opacity)
63-
# Fractions are relative to canvas width/height (0.0–1.0).
64-
# All blobs share a single heavy Gaussian blur filter.
61+
# Technique extracted from Layer5 reference SVGs (Artboard 1.svg):
62+
# - Overlapping full-canvas rectangles with multi-stop linear gradients
63+
# - 10-16 gradient stops per layer for rich, deep color transitions
64+
# - stop-opacity controls where each layer is visible vs transparent,
65+
# allowing underlying layers to show through
66+
# - Radial gradient for the white subject clearing (from chs-2-intro.svg)
67+
# - No blur filter needed — the many intermediate color stops create
68+
# smooth transitions naturally
6569
#
66-
# Three canonical patterns (from the style guide):
70+
# The signature Layer5 gradient ramp (from Artboard 1.svg) has 16 stops
71+
# transitioning from Dark Jungle Green through Charcoal, six intermediate
72+
# blue-greens, Keppel, to Caribbean Green — then back to Charcoal.
6773
#
68-
# CORNER_WARMTH — Gold upper-left, teal right edge/bottom-right, dark
69-
# bottom-left, white center-to-upper-center. Creates a
70-
# sunrise or atmospheric glow effect.
71-
#
72-
# DEEP_SPACE — Dark blue-black majority, teal and gold accents pushed
73-
# to corners, bright white-to-light zone at mid-canvas.
74-
# Like looking through a clearing in a nebula.
75-
#
76-
# The white subject halo is always the LAST blob added (on top), positioned
77-
# where Five will be composed (right 40% of the image, centered vertically).
78-
# It is deliberately off-center and non-circular to feel organic, not like
79-
# a spotlight.
74+
# Each composition layer dict:
75+
# type: "linear" or "radial"
76+
# For linear: x1, y1, x2, y2 (fractions of canvas W,H)
77+
# For radial: cx, cy (fractions), r (fraction of max(W,H))
78+
# stops: [(offset, color, stop_opacity), ...] — stop_opacity optional (default 1.0)
8079

8180
CORNER_WARMTH = [
82-
# cx, cy, rx, ry, color, opacity
83-
#
84-
# Daytime: Saffron sun packed into upper-left corner, Steel Teal sweeping the
85-
# upper-right sky (prominent blue sky field — matching "Twitter post 2.ai" / Kubernetes
86-
# signpost reference), Keppel + Caribbean Green saturating the entire bottom edge,
87-
# large luminous white clearing center-right where Five stands.
88-
# Reference: Layer5 "Twitter post 2.ai" (Kubernetes signpost), "legos.ai", "worship.ai"
89-
(0.05, 0.06, 0.36, 0.30, SAFFRON, 1.00), # deep saffron — upper-left sun, full
90-
(0.22, 0.14, 0.30, 0.26, BANANA, 0.90), # banana mania — warm halo off the sun
91-
(0.82, 0.06, 0.46, 0.38, STEEL_TEAL, 0.92), # steel teal — upper-right sky, prominent
92-
(0.08, 0.86, 0.32, 0.28, TEAL, 0.96), # keppel — bottom-left, vivid
93-
(0.45, 0.94, 0.50, 0.24, TEAL, 0.98), # keppel — bottom center, full-width band
94-
(0.88, 0.88, 0.42, 0.28, TEAL_LIGHT, 0.96), # caribbean green — bottom-right, vivid
95-
(0.44, 0.36, 0.36, 0.30, STEEL_TEAL, 0.68), # steel teal — mid-sky transition
96-
# Large luminous white clearing — center-right, where Five stands
97-
(0.66, 0.44, 0.54, 0.68, WHITE, 0.97),
81+
# Daytime: Saffron upper-left (sun), Keppel/Caribbean Green at right + bottom,
82+
# Dark Jungle Green base at lower-left, MASSIVE white clearing center-right.
83+
# Reference: "4000 members", "Recognition Program", "layer5-hero.webp"
84+
85+
# Layer 1: Teal from the RIGHT — Keppel/Caribbean Green builds from right edge
86+
{"type": "linear",
87+
"x1": 0.0, "y1": 0.5, "x2": 1.0, "y2": 0.5,
88+
"stops": [
89+
(0.00, "#1E2117", 0.0),
90+
(0.20, "#1E2117", 0.0),
91+
(0.35, "#262C27", 0.15),
92+
(0.45, "#323B3B", 0.35),
93+
(0.52, "#3C494E", 0.50),
94+
(0.58, "#375154", 0.60),
95+
(0.63, "#305D5D", 0.70),
96+
(0.68, "#266E6A", 0.80),
97+
(0.73, "#1A847B", 0.88),
98+
(0.78, "#0B9E8F", 0.92),
99+
(0.82, "#00B39F", 0.96),
100+
(0.86, "#00B59F", 0.98),
101+
(0.89, "#00BDA2", 1.00),
102+
(0.92, "#00CAA6", 1.00),
103+
(0.95, "#00D3A9", 1.00),
104+
(1.00, "#3C494E", 0.90),
105+
]},
106+
107+
# Layer 2: Teal from the BOTTOM — ground plane
108+
{"type": "linear",
109+
"x1": 0.5, "y1": 0.0, "x2": 0.5, "y2": 1.0,
110+
"stops": [
111+
(0.00, "#1E2117", 0.0),
112+
(0.30, "#1E2117", 0.0),
113+
(0.45, "#262C27", 0.10),
114+
(0.55, "#323B3B", 0.25),
115+
(0.62, "#3C494E", 0.40),
116+
(0.68, "#375154", 0.55),
117+
(0.73, "#305D5D", 0.65),
118+
(0.78, "#266E6A", 0.75),
119+
(0.82, "#1A847B", 0.85),
120+
(0.86, "#0B9E8F", 0.90),
121+
(0.90, "#00B39F", 0.95),
122+
(0.93, "#00BDA2", 1.00),
123+
(0.96, "#00D3A9", 1.00),
124+
(1.00, "#3C494E", 0.85),
125+
]},
126+
127+
# Layer 3: Saffron from UPPER-LEFT — sun warmth
128+
{"type": "linear",
129+
"x1": -0.05, "y1": -0.05, "x2": 0.75, "y2": 0.75,
130+
"stops": [
131+
(0.00, "#FFF3C5", 0.92),
132+
(0.05, "#FAE6A0", 0.95),
133+
(0.10, "#F5D875", 0.95),
134+
(0.16, "#F0CB45", 0.95),
135+
(0.22, "#EBC017", 1.00),
136+
(0.28, "#D4AD15", 0.95),
137+
(0.34, "#BFA012", 0.88),
138+
(0.40, "#A5870E", 0.78),
139+
(0.46, "#886F0C", 0.65),
140+
(0.52, "#6D5B0D", 0.50),
141+
(0.58, "#56490E", 0.35),
142+
(0.64, "#45390F", 0.22),
143+
(0.70, "#352E11", 0.12),
144+
(0.78, "#2A2613", 0.05),
145+
(0.85, "#1E2117", 0.0),
146+
]},
147+
148+
# Layer 4: White clearing — radial, center-right where Five stands
149+
# Exact ramp from chs-2-intro.svg radialGradient (white→keppel halo)
150+
{"type": "radial", "cx": 0.58, "cy": 0.46, "r": 0.52,
151+
"stops": [
152+
(0.22, "#FFFFFF", 0.97),
153+
(0.32, "#F7FCFC", 0.92),
154+
(0.40, "#E2F6F4", 0.82),
155+
(0.48, "#BFEBE7", 0.68),
156+
(0.56, "#8FDDD4", 0.50),
157+
(0.64, "#52CBBE", 0.32),
158+
(0.74, "#12B8A6", 0.14),
159+
(0.85, "#00B39F", 0.05),
160+
(1.00, "#00B39F", 0.0),
161+
]},
98162
]
99163

100164
DEEP_SPACE = [
101-
# Night sky: Charcoal anchors three corners for deep space darkness,
102-
# Steel Teal dominates the upper sky sweep, Saffron in upper-RIGHT as a
103-
# LARGE vivid color field (not just a corner dot) — matching "Bi-Weekly Meshery
104-
# Build & Release" where saffron occupies 40%+ of the canvas right side, and
105-
# "Newcomers Meeting" where saffron/gold is a dominant warm presence.
106-
# Reference: "Bi-Weekly Meshery Build & Release.ai", "Newcomers Meeting.ai",
107-
# "Meet Five our intergalactic Cloud Native Hero" illustration
108-
(0.04, 0.06, 0.28, 0.30, CHARCOAL, 0.98), # very dark — upper-left corner
109-
(0.04, 0.94, 0.26, 0.24, CHARCOAL, 0.95), # very dark — lower-left corner
110-
(0.96, 0.94, 0.22, 0.20, CHARCOAL, 0.90), # very dark — lower-right corner
111-
(0.88, 0.10, 0.46, 0.44, SAFFRON, 0.90), # gold — upper-RIGHT, large vivid field
112-
(0.76, 0.08, 0.32, 0.28, BANANA, 0.68), # banana — warm halo around the gold
113-
(0.44, 0.18, 0.70, 0.52, STEEL_TEAL, 0.90), # steel teal — large upper-sky sweep
114-
(0.16, 0.52, 0.34, 0.46, STEEL_TEAL, 0.80), # steel teal — mid-left depth layer
115-
# Large luminous clearing — generous, center-weighted where Five stands
116-
(0.60, 0.46, 0.54, 0.66, WHITE, 0.95),
117-
(0.65, 0.42, 0.24, 0.30, OFF_WHITE, 0.90), # bright core
165+
# Night sky: darker overall. Steel Teal concentrated at upper edge,
166+
# fades quickly. Charcoal dominates lower 60%. Saffron accent upper-RIGHT.
167+
# White clearing is tighter — more dark space visible around it.
168+
# Reference: "Meet Five", "Adventures of Five Vol 2" cover
169+
170+
# Layer 1: Steel Teal from the TOP — pulled back, fades by mid-canvas
171+
{"type": "linear",
172+
"x1": 0.5, "y1": -0.1, "x2": 0.5, "y2": 0.8,
173+
"stops": [
174+
(0.00, "#477E96", 1.00),
175+
(0.05, "#477E96", 1.00),
176+
(0.10, "#457A8E", 0.95),
177+
(0.16, "#436F82", 0.88),
178+
(0.22, "#406D7F", 0.78),
179+
(0.28, "#3C5F6D", 0.65),
180+
(0.35, "#375360", 0.50),
181+
(0.42, "#324854", 0.36),
182+
(0.50, "#2D3E49", 0.24),
183+
(0.58, "#29353E", 0.14),
184+
(0.68, "#252D33", 0.06),
185+
(0.80, "#1E2117", 0.0),
186+
]},
187+
188+
# Layer 2: Steel Teal from LEFT edge — subtle, fades quickly
189+
{"type": "linear",
190+
"x1": -0.1, "y1": 0.4, "x2": 0.8, "y2": 0.4,
191+
"stops": [
192+
(0.00, "#477E96", 0.75),
193+
(0.06, "#457A8E", 0.65),
194+
(0.14, "#406D7F", 0.50),
195+
(0.22, "#3C5F6D", 0.36),
196+
(0.30, "#375360", 0.24),
197+
(0.38, "#324854", 0.14),
198+
(0.48, "#2D3E49", 0.06),
199+
(0.60, "#1E2117", 0.0),
200+
]},
201+
202+
# Layer 3: Charcoal reinforcement — darker overall, starts earlier
203+
{"type": "linear",
204+
"x1": 0.5, "y1": 0.0, "x2": 0.5, "y2": 1.0,
205+
"stops": [
206+
(0.00, "#3C494F", 0.0),
207+
(0.25, "#3C494F", 0.10),
208+
(0.40, "#3C494F", 0.30),
209+
(0.50, "#3C494F", 0.55),
210+
(0.60, "#3C494F", 0.75),
211+
(0.72, "#3C494F", 0.90),
212+
(0.85, "#3C494F", 0.96),
213+
(1.00, "#3C494F", 1.00),
214+
]},
215+
216+
# Layer 4: Extra darkness from lower-left corner diagonal
217+
{"type": "linear",
218+
"x1": 0.9, "y1": -0.1, "x2": -0.1, "y2": 1.1,
219+
"stops": [
220+
(0.00, "#1E2117", 0.0),
221+
(0.35, "#1E2117", 0.0),
222+
(0.50, "#1E2117", 0.25),
223+
(0.65, "#1E2117", 0.55),
224+
(0.80, "#1E2117", 0.80),
225+
(1.00, "#1E2117", 0.95),
226+
]},
227+
228+
# Layer 5: Saffron star UPPER-RIGHT — warm accent
229+
{"type": "linear",
230+
"x1": 0.15, "y1": 0.80, "x2": 1.05, "y2": -0.10,
231+
"stops": [
232+
(0.00, "#1E2117", 0.0),
233+
(0.40, "#1E2117", 0.0),
234+
(0.50, "#45390F", 0.10),
235+
(0.56, "#6D5B0D", 0.25),
236+
(0.62, "#886F0C", 0.40),
237+
(0.68, "#A5870E", 0.58),
238+
(0.74, "#BFA012", 0.72),
239+
(0.80, "#D4AD15", 0.84),
240+
(0.85, "#EBC017", 0.94),
241+
(0.90, "#F0CB45", 0.96),
242+
(0.94, "#F5D875", 0.92),
243+
(0.97, "#FFF3C5", 0.85),
244+
(1.00, "#3C494E", 0.60),
245+
]},
246+
247+
# Layer 6: White clearing — tighter radius, less reach
248+
{"type": "radial", "cx": 0.56, "cy": 0.46, "r": 0.46,
249+
"stops": [
250+
(0.18, "#FFFFFF", 0.96),
251+
(0.28, "#F7FCFC", 0.88),
252+
(0.36, "#E2F6F4", 0.74),
253+
(0.44, "#BFEBE7", 0.56),
254+
(0.52, "#8FDDD4", 0.38),
255+
(0.62, "#52CBBE", 0.20),
256+
(0.72, "#12B8A6", 0.08),
257+
(0.84, "#00B39F", 0.02),
258+
(1.00, "#00B39F", 0.0),
259+
]},
118260
]
119261

120262
# Map category → composition. Corner Warmth is the warmer, more energetic look;
@@ -147,45 +289,76 @@
147289

148290
def bg_blobs_svg(category, W, H):
149291
"""
150-
Return (filter_def, background_svg) for the full-canvas freeform gradient.
292+
Return (defs_block, background_svg) for the multi-stop gradient background.
151293
152-
filter_def — goes inside the top-level <defs> block
153-
background_svg — the base rect + blurred color blobs
294+
Uses the same technique as Layer5's official illustrations (Artboard 1.svg):
295+
overlapping layers with multi-stop gradients (10-16 stops per layer) and
296+
stop-opacity for compositing. No blur filter needed — the many intermediate
297+
color stops create smooth, rich transitions naturally.
154298
155-
Blur stdDeviation scales with canvas width: ~10% of width for a
156-
1200px canvas gives stdDeviation=120, matching the style guide reference.
299+
defs_block — gradient definitions, goes inside the top-level <defs>
300+
background_svg — the base rect + gradient layers
157301
"""
158302
composition = CATEGORY_COMPOSITION.get(category, CORNER_WARMTH)
159-
blur_std = round(W * 0.10) # 120px at 1200px canvas — wide, smooth color transitions
160303

161-
filter_def = (
162-
f'<filter id="bgBlur" x="-100%" y="-100%" width="300%" height="300%">\n'
163-
f' <feGaussianBlur stdDeviation="{blur_std}"/>\n'
164-
f' </filter>'
165-
)
304+
gradient_defs = []
305+
layer_rects = []
306+
307+
for i, layer in enumerate(composition):
308+
grad_id = f"bgGrad{i}"
309+
310+
# Build stop elements
311+
stop_lines = []
312+
for s in layer["stops"]:
313+
offset, color = s[0], s[1]
314+
opacity_attr = ""
315+
if len(s) > 2 and s[2] < 1.0:
316+
opacity_attr = f' stop-opacity="{s[2]}"'
317+
stop_lines.append(
318+
f' <stop offset="{offset}" stop-color="{color}"{opacity_attr}/>'
319+
)
320+
stops_xml = "\n".join(stop_lines)
321+
322+
if layer["type"] == "linear":
323+
x1 = layer["x1"] * W
324+
y1 = layer["y1"] * H
325+
x2 = layer["x2"] * W
326+
y2 = layer["y2"] * H
327+
gradient_defs.append(
328+
f' <linearGradient id="{grad_id}" '
329+
f'gradientUnits="userSpaceOnUse" '
330+
f'x1="{x1:.0f}" y1="{y1:.0f}" x2="{x2:.0f}" y2="{y2:.0f}">\n'
331+
f'{stops_xml}\n'
332+
f' </linearGradient>'
333+
)
334+
elif layer["type"] == "radial":
335+
cx = layer["cx"] * W
336+
cy = layer["cy"] * H
337+
r = layer["r"] * max(W, H)
338+
gradient_defs.append(
339+
f' <radialGradient id="{grad_id}" '
340+
f'gradientUnits="userSpaceOnUse" '
341+
f'cx="{cx:.0f}" cy="{cy:.0f}" r="{r:.0f}">\n'
342+
f'{stops_xml}\n'
343+
f' </radialGradient>'
344+
)
166345

167-
ellipses = []
168-
for cx_f, cy_f, rx_f, ry_f, color, opacity in composition:
169-
cx = cx_f * W
170-
cy = cy_f * H
171-
rx = rx_f * W
172-
ry = ry_f * H
173-
ellipses.append(
174-
f' <ellipse cx="{cx:.0f}" cy="{cy:.0f}" '
175-
f'rx="{rx:.0f}" ry="{ry:.0f}" '
176-
f'fill="{color}" opacity="{opacity}"/>'
346+
layer_rects.append(
347+
f' <rect width="{W}" height="{H}" fill="url(#{grad_id})"/>'
177348
)
178349

350+
defs_block = "\n".join(gradient_defs)
351+
179352
background_svg = (
180353
f'<!-- Base background -->\n'
181354
f' <rect width="{W}" height="{H}" fill="{EERIE_BLACK}"/>\n'
182-
f' <!-- Freeform gradient blobs (all share heavy Gaussian blur) -->\n'
183-
f' <g filter="url(#bgBlur)" clip-path="url(#canvas)">\n'
184-
+ '\n'.join(ellipses)
355+
f' <!-- Multi-stop gradient layers (Layer5 illustration technique) -->\n'
356+
f' <g clip-path="url(#canvas)">\n'
357+
+ '\n'.join(layer_rects)
185358
+ '\n </g>'
186359
)
187360

188-
return filter_def, background_svg
361+
return defs_block, background_svg
189362

190363

191364
# ── Close-range Five glow ─────────────────────────────────────────────────
@@ -464,6 +637,7 @@ def generate_hero_svg(title, subtitle, category, output_path, repo_root,
464637
</linearGradient>
465638
{bg_filter_def}
466639
{glow_filter_def}
640+
<!-- Note: bg_filter_def now contains gradient definitions, not a blur filter -->
467641
</defs>
468642
469643
{bg_svg}

src/collections/blog/2026/04-03-claude-code-skills-not-found-sessionstart-hook/hero-image.svg

Lines changed: 149 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)