From claude-wayfinder
Materialize the claude-wayfinder Python venv at ${CLAUDE_PLUGIN_DATA}/venv/ and write the setup-state flag. Use when: - User types /setup-wayfinder - User says "set up claude-wayfinder", "install wayfinder dependencies" - User says "wayfinder isn't working", "fix wayfinder", "repair wayfinder" - SessionStart banner indicates setup is required and the user wants to proceed - Plugin version bumped and re-setup needed Do NOT trigger on casual mentions of "wayfinder" without setup/install/fix intent.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-wayfinder:setup-wayfinderThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Materialize the Python venv at `${CLAUDE_PLUGIN_DATA}/venv/` so plugin hooks can spawn a Python that has `claude_wayfinder` importable. Write the setup-state flag so hooks know setup completed.
Materialize the Python venv at ${CLAUDE_PLUGIN_DATA}/venv/ so plugin hooks can spawn a Python that has claude_wayfinder importable. Write the setup-state flag so hooks know setup completed.
The behavior described below is mirrored by tests/integration/setup_pipeline.py. If you change anything here, update that file too (CI's test_skill_pipeline_sync.py enforces this).
${CLAUDE_PLUGIN_DATA}The plugin data directory path is keyed <plugin>-<marketplace> by the harness, and the same plugin resolves under different marketplace keys across surfaces — claude-wayfinder-glitchwerks on a CLI surface, claude-wayfinder-inline on a desktop/ccd surface. Two sources are available, in priority order:
$CLAUDE_PLUGIN_DATA (no braces) — the test seam, but the harness sets it to whichever plugin invoked the current surface, so another plugin's data dir can leak in (e.g. codex-inline). Honor it only when its basename is a same-plugin key: claude-wayfinder-<marketplace> with exactly one marketplace segment after the plugin name (-glitchwerks, -inline, …). This admits every marketplace variant while rejecting two leak classes — unrelated plugins (codex-inline) and prefix-colliding sibling plugins whose own name starts with claude-wayfinder- (e.g. claude-wayfinder-helper → key claude-wayfinder-helper-inline, which has a second - segment). Do not require an exact -glitchwerks match — that is the bug this guard replaces (it rejected the legitimate -inline desktop key and silently misinstalled into the CLI-keyed dir, leaving every desktop session stuck on the "requires setup" banner). Do not loosen it to a bare claude-wayfinder-* prefix either — that re-admits the sibling-plugin collision.${CLAUDE_PLUGIN_DATA} (braces) — the harness substitutes this token in the skill body at load time with this session's correct data dir. Prefer it over a hardcoded -glitchwerks slug whenever the runtime env var is unusable (cross-plugin leak, or unset).claude-wayfinder-glitchwerks) — last resort only, for raw execution outside the harness where neither source above is available.Use the Bash tool:
PLUGIN_NAME="claude-wayfinder"
EXPECTED_SLUG="claude-wayfinder-glitchwerks"
# Harness-rendered literal (braces): substituted at skill-load with THIS session's
# data dir (…/claude-wayfinder-inline on desktop, …/claude-wayfinder-glitchwerks on
# CLI) — correct per-session. Keep the braces; do NOT rewrite to $CLAUDE_PLUGIN_DATA.
HARNESS_DATA="${CLAUDE_PLUGIN_DATA}"
if [ -n "$CLAUDE_PLUGIN_DATA" ]; then
ACTUAL_SLUG=$(basename "$CLAUDE_PLUGIN_DATA")
case "$ACTUAL_SLUG" in
${PLUGIN_NAME}-*-*)
# Prefix-colliding SIBLING plugin: a different plugin whose name starts with
# "claude-wayfinder-" (e.g. claude-wayfinder-helper → key
# claude-wayfinder-helper-inline) leaves TWO segments after the plugin name.
# Our own keys are exactly claude-wayfinder-<marketplace> (one segment, e.g.
# -inline | -glitchwerks). Reject the collision — use the harness literal.
echo "Warning: \$CLAUDE_PLUGIN_DATA basename '$ACTUAL_SLUG' has extra segments after '${PLUGIN_NAME}-' (prefix-colliding sibling plugin?). Using harness-rendered data dir." >&2
PLUGIN_DATA="$HARNESS_DATA" ;;
${PLUGIN_NAME}-*)
# Same-plugin key, single marketplace segment (e.g. claude-wayfinder-inline |
# -glitchwerks) — honor it.
PLUGIN_DATA="$CLAUDE_PLUGIN_DATA" ;;
*)
# Cross-plugin leak (e.g. codex-inline) — fall back to the harness literal.
echo "Warning: \$CLAUDE_PLUGIN_DATA basename '$ACTUAL_SLUG' is not a ${PLUGIN_NAME}-* dir (cross-plugin leak?). Using harness-rendered data dir." >&2
PLUGIN_DATA="$HARNESS_DATA" ;;
esac
else
PLUGIN_DATA="$HARNESS_DATA"
fi
# Safety net: if the harness literal was never interpolated (raw execution outside
# the harness leaves it empty), compute the canonical slug as a last resort.
if [ -z "$PLUGIN_DATA" ]; then
PLUGIN_DATA="$HOME/.claude/plugins/data/$EXPECTED_SLUG"
fi
# Normalize Git-Bash POSIX paths (/c/Users/...) to native Windows form (C:/Users/...)
# so the venv_path stored in setup-state.json (Step 7) is readable by Node's
# fs.existsSync on Windows. Git Bash expands $HOME to /c/Users/... rather than
# C:/Users/..., which Node does not recognise as a valid Windows path (#186).
# On non-Windows or paths that don't match the /X/... pattern, this is a no-op.
case "$PLUGIN_DATA" in
/[a-zA-Z]/*)
drive=$(printf '%s' "$PLUGIN_DATA" | cut -c2 | tr '[:lower:]' '[:upper:]')
rest=$(printf '%s' "$PLUGIN_DATA" | cut -c3-)
PLUGIN_DATA="${drive}:${rest}"
;;
esac
mkdir -p "$PLUGIN_DATA"
echo "$PLUGIN_DATA"
The test seam is preserved: tests that want to override the path can still set $CLAUDE_PLUGIN_DATA to any directory whose basename is a single-segment same-plugin key claude-wayfinder-<seg> (e.g., a tmpdir created as …/claude-wayfinder-XXXX/, where XXXX has no further -). Cross-plugin leaks (codex-inline) and prefix-colliding sibling plugins (claude-wayfinder-helper-inline) are rejected and no longer cause silent misinstall into another plugin's data dir.
Try these candidates in order, stopping at the first that probes successfully:
interpreter field (if a flag is currently being re-setup).$CLAUDE_WAYFINDER_BOOTSTRAP_PYTHON if set.py -3 on Windows.python3 then python on PATH.Probe each candidate with:
<candidate> -c "import sys; sys.exit(0 if sys.version_info >= (3, 11) else 1)"
Exit 0 = success, save the candidate as PYTHON.
If all candidates fail, ask the user:
No Python ≥3.11 found. I tried: $CLAUDE_WAYFINDER_BOOTSTRAP_PYTHON, py -3, python3, python. Please provide an absolute path to a Python ≥3.11 interpreter (e.g.,
C:\Python313\python.exeor/usr/local/bin/python3.12). If you don't have one installed, you'll need to install Python first.
Probe the user-provided path the same way. If it works, save it (will be persisted in the flag's interpreter field for future re-setup runs).
Per spec § 2 D4, always wipe + recreate. No idempotency.
rm -rf "$PLUGIN_DATA/venv"
(On Windows PowerShell: Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:PLUGIN_DATA\venv")
"$PYTHON" -m venv "$PLUGIN_DATA/venv"
If this fails:
sudo apt install python3-venv is often needed.The version to install is the plugin's current version, read from ${CLAUDE_PLUGIN_ROOT}/pyproject.toml (preferred) or ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json. Pin exactly:
VENV_PYTHON="$PLUGIN_DATA/venv/bin/python" # or Scripts/python.exe on Windows
"$VENV_PYTHON" -m pip install "claude-wayfinder==$PLUGIN_VERSION"
If pip fails:
"$VENV_PYTHON" -c "import claude_wayfinder"
If this fails after a successful pip install, the wheel is corrupt:
pip cache purge then retry.Always-wipe contract: the Write tool's read-before-overwrite invariant is hostile on re-setup, where the prior file exists but its contents are about to be discarded — use a shell heredoc instead.
Bash (Git Bash on Windows or POSIX):
TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > "$PLUGIN_DATA/setup-state.json" <<EOF
{
"version": "$PLUGIN_VERSION",
"venv_path": "$PLUGIN_DATA/venv",
"interpreter": "$PYTHON",
"installed_at": "$TS"
}
EOF
PowerShell:
$ts = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
@"
{
"version": "$PluginVersion",
"venv_path": "$PluginData/venv",
"interpreter": "$Python",
"installed_at": "$ts"
}
"@ | Set-Content -Path "$PluginData/setup-state.json" -NoNewline
If the write fails (disk full, permission), wipe the venv (otherwise orphaned), surface the write error.
On success, tell the user:
✓ claude-wayfinder setup complete.
- venv:
<path>- interpreter:
<which Python was used>- version:
<plugin version>Open a new session for the dispatch matcher and catalog refresh to activate. The next
check-catalog-health.jsSessionStart hook will see the flag and proceed normally.
npx claudepluginhub glitchwerks/claude-wayfinder --plugin claude-wayfinderProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.