import { e as createAstro, f as createComponent, m as maybeRenderHead, h as addAttribute, r as renderTemplate, k as renderComponent, l as renderScript } from '../chunks/astro/server_CF97kUu8.mjs'; import 'piccolore'; import { _ as _export_sfc, $ as $$Base } from '../chunks/_plugin-vue_export-helper_CEgY73aA.mjs'; import 'clsx'; import { useSSRContext, defineComponent, ref, computed, onMounted, watch, nextTick, mergeProps } from 'vue'; import { ssrRenderAttrs, ssrRenderAttr, ssrRenderList, ssrInterpolate, ssrIncludeBooleanAttr, ssrLooseContain, ssrLooseEqual, ssrRenderClass } from 'vue/server-renderer'; import { l as listSkills } from '../chunks/skills_BacVQUiS.mjs'; import { b as getAllStats } from '../chunks/stats_CaDi9y9J.mjs'; import { i as isPowerShell, a as buildSyncScriptPS, b as buildSyncScript } from '../chunks/sync_BEq_wzpT.mjs'; /* empty css */ export { renderers } from '../renderers.mjs'; const $$Astro$1 = createAstro("https://skills.here.run.place"); const $$SkillCard = createComponent(($$result, $$props, $$slots) => { const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots); Astro2.self = $$SkillCard; const { slug, name, description, "allowed-tools": allowedTools, tags = [], author, forkCount = 0, downloads = 0, pushes = 0, lastPushedAt } = Astro2.props; const updatedLabel = lastPushedAt ? new Date(lastPushedAt).toLocaleDateString("en-US", { month: "short", day: "numeric" }) : null; const truncated = description.length > 120 ? description.slice(0, 120) + "..." : description; return renderTemplate`${maybeRenderHead()}

${name}

${truncated && renderTemplate`

${truncated}

`} ${allowedTools.length > 0 && renderTemplate`
${allowedTools.map((tool) => renderTemplate` ${tool} `)}
`} ${tags.length > 0 && renderTemplate`
${tags.map((tag) => renderTemplate` ${tag} `)}
`}
${author && renderTemplate`

by ${author}

`} ${forkCount > 0 && renderTemplate` ${forkCount} `} ${downloads > 0 && renderTemplate` ${downloads} `} ${pushes > 0 && renderTemplate` ${pushes} `} ${updatedLabel && renderTemplate`${updatedLabel}`}
`; }, "/Users/alex/projects/skillit/src/components/SkillCard.astro", void 0); const PER_PAGE_GRID = 12; const PER_PAGE_TABLE = 20; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "SkillSearch", props: { authors: {}, tags: {}, totalCount: {} }, setup(__props, { expose: __expose }) { __expose(); const props = __props; const authorList = props.authors ? props.authors.split(",").map((a) => a.trim()).filter(Boolean) : []; const tagList = props.tags ? props.tags.split(",").map((t) => t.trim()).filter(Boolean) : []; const query = ref(""); const forkFilter = ref(""); const savedView = typeof localStorage !== "undefined" && localStorage.getItem("skillsViewMode"); const viewMode = ref(savedView === "table" ? "table" : "grid"); const currentPage = ref(1); const filteredCount = ref(props.totalCount || 0); const perPage = computed(() => viewMode.value === "grid" ? PER_PAGE_GRID : PER_PAGE_TABLE); const totalPages = computed(() => Math.max(1, Math.ceil(filteredCount.value / perPage.value))); const rangeStart = computed(() => filteredCount.value === 0 ? 0 : (currentPage.value - 1) * perPage.value + 1); const rangeEnd = computed(() => Math.min(currentPage.value * perPage.value, filteredCount.value)); const visiblePages = computed(() => { const pages = []; const total = totalPages.value; const cur = currentPage.value; const maxVisible = 7; if (total <= maxVisible) { for (let i = 1; i <= total; i++) pages.push(i); } else { const half = Math.floor(maxVisible / 2); let start = Math.max(1, cur - half); let end = start + maxVisible - 1; if (end > total) { end = total; start = end - maxVisible + 1; } for (let i = start; i <= end; i++) pages.push(i); } return pages; }); const selectedAuthors = ref([]); const authorQuery = ref(""); const authorOpen = ref(false); const authorInputEl = ref(); const authorSuggestions = computed(() => { const q = authorQuery.value.toLowerCase().trim(); const selected = new Set(selectedAuthors.value.map((a) => a.toLowerCase())); return authorList.filter((a) => !selected.has(a.toLowerCase()) && (!q || a.toLowerCase().includes(q))); }); let authorBlurTimer; function onAuthorBlur() { authorBlurTimer = setTimeout(() => { authorOpen.value = false; }, 200); } function addAuthor(author) { clearTimeout(authorBlurTimer); if (!selectedAuthors.value.some((a) => a.toLowerCase() === author.toLowerCase())) { selectedAuthors.value.push(author); } authorQuery.value = ""; authorInputEl.value?.focus(); } function removeAuthor(author) { selectedAuthors.value = selectedAuthors.value.filter((a) => a !== author); } function onAuthorEnter() { if (authorSuggestions.value.length > 0) { addAuthor(authorSuggestions.value[0]); } } function onAuthorBackspace() { if (!authorQuery.value && selectedAuthors.value.length > 0) { selectedAuthors.value.pop(); } } const selectedTags = ref([]); const tagQuery = ref(""); const tagOpen = ref(false); const tagInputEl = ref(); const tagSuggestions = computed(() => { const q = tagQuery.value.toLowerCase().trim(); const selected = new Set(selectedTags.value.map((t) => t.toLowerCase())); return tagList.filter((t) => !selected.has(t.toLowerCase()) && (!q || t.toLowerCase().includes(q))); }); let tagBlurTimer; function onTagBlur() { tagBlurTimer = setTimeout(() => { tagOpen.value = false; }, 200); } function addTag(tag) { clearTimeout(tagBlurTimer); if (!selectedTags.value.some((t) => t.toLowerCase() === tag.toLowerCase())) { selectedTags.value.push(tag); } tagQuery.value = ""; tagInputEl.value?.focus(); } function removeTag(tag) { selectedTags.value = selectedTags.value.filter((t) => t !== tag); } function onTagEnter() { if (tagSuggestions.value.length > 0) { addTag(tagSuggestions.value[0]); } } function onTagBackspace() { if (!tagQuery.value && selectedTags.value.length > 0) { selectedTags.value.pop(); } } function setView(mode) { viewMode.value = mode; localStorage.setItem("skillsViewMode", mode); const grid = document.getElementById("skills-grid"); const table = document.getElementById("skills-table"); if (grid && table) { grid.classList.toggle("hidden", mode !== "grid"); table.classList.toggle("hidden", mode !== "table"); } currentPage.value = 1; nextTick(() => applyFilters()); } onMounted(() => { if (viewMode.value !== "grid") { setView(viewMode.value); } }); const hasActiveFilters = computed( () => query.value || selectedAuthors.value.length > 0 || selectedTags.value.length > 0 || forkFilter.value ); function applyFilters() { const q = query.value.toLowerCase().trim(); const authors = selectedAuthors.value.map((a) => a.toLowerCase()); const tags = selectedTags.value.map((t) => t.toLowerCase()); const minForks = forkFilter.value ? parseInt(forkFilter.value) : 0; const activeId = viewMode.value === "grid" ? "skills-grid" : "skills-table"; const inactiveId = viewMode.value === "grid" ? "skills-table" : "skills-grid"; const activeItems = Array.from(document.querySelectorAll(`#${activeId} [data-skill]`)); const inactiveItems = document.querySelectorAll(`#${inactiveId} [data-skill]`); inactiveItems.forEach((el) => el.style.display = "none"); const matching = []; activeItems.forEach((card) => { const name = card.dataset.name || ""; const desc = card.dataset.description || ""; const tools = card.dataset.tools || ""; const cardAuthor = card.dataset.author || ""; const cardTags = (card.dataset.tags || "").split(",").filter(Boolean); const forks = parseInt(card.dataset.forks || "0"); const matchText = !q || name.includes(q) || desc.includes(q) || tools.includes(q) || cardTags.some((t) => t.includes(q)); const matchAuthor = authors.length === 0 || authors.some((a) => cardAuthor.includes(a)); const matchTag = tags.length === 0 || tags.every((t) => cardTags.includes(t)); const matchForks = forks >= minForks; if (matchText && matchAuthor && matchTag && matchForks) { matching.push(card); } }); filteredCount.value = matching.length; const maxPage = Math.max(1, Math.ceil(matching.length / perPage.value)); if (currentPage.value > maxPage) { currentPage.value = maxPage; } const start = (currentPage.value - 1) * perPage.value; const end = start + perPage.value; activeItems.forEach((card) => { const idx = matching.indexOf(card); if (idx === -1) { card.style.display = "none"; } else if (idx >= start && idx < end) { card.style.display = ""; } else { card.style.display = "none"; } }); } function goToPage(page) { if (page < 1 || page > totalPages.value) return; currentPage.value = page; applyFilters(); } function reset() { query.value = ""; selectedAuthors.value = []; authorQuery.value = ""; selectedTags.value = []; tagQuery.value = ""; forkFilter.value = ""; currentPage.value = 1; } watch([query, selectedAuthors, selectedTags, forkFilter], () => { currentPage.value = 1; applyFilters(); }, { deep: true }); const __returned__ = { props, authorList, tagList, query, forkFilter, savedView, viewMode, currentPage, filteredCount, PER_PAGE_GRID, PER_PAGE_TABLE, perPage, totalPages, rangeStart, rangeEnd, visiblePages, selectedAuthors, authorQuery, authorOpen, authorInputEl, authorSuggestions, get authorBlurTimer() { return authorBlurTimer; }, set authorBlurTimer(v) { authorBlurTimer = v; }, onAuthorBlur, addAuthor, removeAuthor, onAuthorEnter, onAuthorBackspace, selectedTags, tagQuery, tagOpen, tagInputEl, tagSuggestions, get tagBlurTimer() { return tagBlurTimer; }, set tagBlurTimer(v) { tagBlurTimer = v; }, onTagBlur, addTag, removeTag, onTagEnter, onTagBackspace, setView, hasActiveFilters, applyFilters, goToPage, reset }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }); function _sfc_ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) { _push(`
`); ssrRenderList($setup.selectedAuthors, (a) => { _push(`${ssrInterpolate(a)} `); }); _push(`
`); if ($setup.authorOpen && $setup.authorSuggestions.length > 0) { _push(`
`); ssrRenderList($setup.authorSuggestions, (a) => { _push(``); }); _push(`
`); } else { _push(``); } _push(`
`); ssrRenderList($setup.selectedTags, (t) => { _push(`${ssrInterpolate(t)} `); }); _push(`
`); if ($setup.tagOpen && $setup.tagSuggestions.length > 0) { _push(`
`); ssrRenderList($setup.tagSuggestions, (t) => { _push(``); }); _push(`
`); } else { _push(``); } _push(`
`); if ($setup.hasActiveFilters) { _push(``); } else { _push(``); } _push(`
`); if ($setup.totalPages > 1) { _push(`
Showing ${ssrInterpolate($setup.rangeStart)}–${ssrInterpolate($setup.rangeEnd)} of ${ssrInterpolate($setup.filteredCount)}
Prev `); ssrRenderList($setup.visiblePages, (p) => { _push(``); }); _push(` Next
`); } else { _push(``); } _push(``); } const _sfc_setup = _sfc_main.setup; _sfc_main.setup = (props, ctx) => { const ssrContext = useSSRContext(); (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/components/SkillSearch.vue"); return _sfc_setup ? _sfc_setup(props, ctx) : void 0; }; const SkillSearch = /* @__PURE__ */ _export_sfc(_sfc_main, [["ssrRender", _sfc_ssrRender]]); const $$Astro = createAstro("https://skills.here.run.place"); const $$Index = createComponent(async ($$result, $$props, $$slots) => { const Astro2 = $$result.createAstro($$Astro, $$props, $$slots); Astro2.self = $$Index; const accept = Astro2.request.headers.get("accept") || ""; if (!accept.includes("text/html")) { const ps = isPowerShell(Astro2.request); const script = ps ? await buildSyncScriptPS(Astro2.url.origin, ".claude\\skills") : await buildSyncScript(Astro2.url.origin, ".claude/skills"); return new Response(script, { headers: { "Content-Type": "text/plain; charset=utf-8" } }); } const skills = await listSkills(); const forkCounts = /* @__PURE__ */ new Map(); for (const s of skills) { if (s["fork-of"]) { forkCounts.set(s["fork-of"], (forkCounts.get(s["fork-of"]) || 0) + 1); } } const authors = [...new Set(skills.map((s) => s.author).filter(Boolean))].sort(); const allTags = [...new Set(skills.flatMap((s) => s.tags))].sort(); const allStats = await getAllStats(); return renderTemplate`${renderComponent($$result, "Base", $$Base, { "title": "Skills", "data-astro-cid-j7pv25f6": true }, { "default": async ($$result2) => renderTemplate`${skills.length === 0 ? renderTemplate`${maybeRenderHead()}

No skills yet

Create your first skill to get started.

Create your first skill
` : renderTemplate`

Skills

Manage and distribute Claude Code skills. Skills are prompt files (.md) that Claude loads automatically to learn custom behaviors and workflows.

Create reusable skills to standardize how Claude handles commits, code reviews, testing, deployments, and more across your team. Share them instantly with a single curl command.

Quick install

Sync all skills to your project. They'll be saved to .claude/skills/ and Claude Code picks them up on the next conversation.

curl -fsSL ${Astro2.url.origin} | bash
Install globally
curl -fsSL ${Astro2.url.origin}/gi | bash

Quick push

Push your local skills to the server. Run from your project root — it reads .claude/skills/*.md and uploads them.

curl -fsSL ${Astro2.url.origin}/p | bash
Push a specific skill
curl -fsSL ${Astro2.url.origin}/p | bash -s skill-name
${renderComponent($$result2, "SkillSearch", SkillSearch, { "authors": authors.join(","), "tags": allTags.join(","), "totalCount": skills.length, "client:load": true, "client:component-hydration": "load", "client:component-path": "/Users/alex/projects/skillit/src/components/SkillSearch.vue", "client:component-export": "default", "data-astro-cid-j7pv25f6": true })}
${skills.map((skill) => renderTemplate`
${renderComponent($$result2, "SkillCard", $$SkillCard, { ...skill, "forkCount": forkCounts.get(skill.slug) || 0, "downloads": allStats[skill.slug]?.downloads || 0, "pushes": allStats[skill.slug]?.pushes || 0, "lastPushedAt": allStats[skill.slug]?.lastPushedAt || null, "data-astro-cid-j7pv25f6": true })}
`)}
`}` })} ${renderScript($$result, "/Users/alex/projects/skillit/src/pages/index.astro?astro&type=script&index=0&lang.ts")}`; }, "/Users/alex/projects/skillit/src/pages/index.astro", void 0); const $$file = "/Users/alex/projects/skillit/src/pages/index.astro"; const $$url = ""; const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ __proto__: null, default: $$Index, file: $$file, url: $$url }, Symbol.toStringTag, { value: 'Module' })); const page = () => _page; export { page };