ai-agent-skills 3.4.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -6
- package/package.json +1 -1
- package/skills.json +3 -3
- package/tui/index.mjs +77 -271
package/README.md
CHANGED
|
@@ -27,6 +27,14 @@ The library is organized the way I actually work:
|
|
|
27
27
|
If you want the broad open ecosystem, use `skills.sh`.
|
|
28
28
|
If you want my shelves, use this repo.
|
|
29
29
|
|
|
30
|
+
## Why This Repo Still Exists
|
|
31
|
+
|
|
32
|
+
I launched this on December 17, 2025, before `skills.sh` existed and before the ecosystem had a clear default universal installer.
|
|
33
|
+
|
|
34
|
+
Originally this repo was that universal installer. That part still works.
|
|
35
|
+
|
|
36
|
+
What makes it worth keeping now is the library itself: the shelves, the provenance, and the editorial judgment. `skills.sh` is the broad open ecosystem. This repo is the smaller personal library I actually reach for.
|
|
37
|
+
|
|
30
38
|
## The Two-Tier Model
|
|
31
39
|
|
|
32
40
|
Every skill in the library is one of two things:
|
|
@@ -69,14 +77,18 @@ Legacy agent-specific targets still work through `--agent <name>`.
|
|
|
69
77
|
|
|
70
78
|
## How To Read The Library
|
|
71
79
|
|
|
72
|
-
There are
|
|
80
|
+
There are two main ways to browse it:
|
|
73
81
|
|
|
74
82
|
| View | Why it exists | Start here |
|
|
75
83
|
| --- | --- | --- |
|
|
76
|
-
| Shelves | The main way to understand the library | `npx ai-agent-skills list` |
|
|
77
|
-
|
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
| Shelves | The main way to understand the library: start with the kind of work, then drill into the small set of picks on that shelf. | `npx ai-agent-skills list` |
|
|
85
|
+
| Sources | The provenance view: see which publishers feed which shelves and branches. | `npx ai-agent-skills info frontend-design` |
|
|
86
|
+
|
|
87
|
+
Secondary surfaces still exist, but they are not the main taxonomy:
|
|
88
|
+
|
|
89
|
+
- `npx ai-agent-skills browse` for the TUI
|
|
90
|
+
- `npx ai-agent-skills list --collection my-picks` for a cross-shelf starter stack
|
|
91
|
+
- `npx ai-agent-skills curate review` for the curator cleanup queue
|
|
80
92
|
|
|
81
93
|
## Shelves
|
|
82
94
|
|
|
@@ -135,7 +147,7 @@ It adds metadata and editorial placement:
|
|
|
135
147
|
For existing picks, `curate` is the fast loop:
|
|
136
148
|
|
|
137
149
|
```bash
|
|
138
|
-
npx ai-agent-skills curate frontend-design --branch "
|
|
150
|
+
npx ai-agent-skills curate frontend-design --branch "Frontend (Anthropic)"
|
|
139
151
|
npx ai-agent-skills curate frontend-design --why "A stronger note that matches how I actually use it."
|
|
140
152
|
npx ai-agent-skills curate review
|
|
141
153
|
```
|
package/package.json
CHANGED
package/skills.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.4.
|
|
2
|
+
"version": "3.4.1",
|
|
3
3
|
"updated": "2026-03-21T00:00:00Z",
|
|
4
4
|
"total": 35,
|
|
5
5
|
"workAreas": [
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"description": "Create distinctive, production-grade frontend interfaces with high design quality. Use for building web components, pages, dashboards, HTML/CSS layouts, or styling any web UI.",
|
|
128
128
|
"category": "development",
|
|
129
129
|
"workArea": "frontend",
|
|
130
|
-
"branch": "
|
|
130
|
+
"branch": "Frontend (Anthropic)",
|
|
131
131
|
"author": "anthropics",
|
|
132
132
|
"source": "anthropics/skills",
|
|
133
133
|
"license": "Apache-2.0",
|
|
@@ -930,7 +930,7 @@
|
|
|
930
930
|
"description": "Use when the task asks for a visually strong landing page, website, app, prototype, demo, or game UI. This skill enforces restrained composition, image-led hierarchy, cohesive content structure, and tasteful motion while avoiding generic cards, weak branding, and UI clutter.",
|
|
931
931
|
"category": "development",
|
|
932
932
|
"workArea": "frontend",
|
|
933
|
-
"branch": "
|
|
933
|
+
"branch": "Frontend (OpenAI)",
|
|
934
934
|
"author": "openai",
|
|
935
935
|
"source": "openai/skills",
|
|
936
936
|
"license": "MIT",
|
package/tui/index.mjs
CHANGED
|
@@ -275,6 +275,10 @@ function fitText(text, maxLength) {
|
|
|
275
275
|
return `${value.slice(0, maxLength - 1)}…`;
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
function formatCount(count, singular, plural = `${singular}s`) {
|
|
279
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
280
|
+
}
|
|
281
|
+
|
|
278
282
|
function shellQuote(value) {
|
|
279
283
|
const stringValue = String(value);
|
|
280
284
|
if (/^[a-zA-Z0-9._:/=@-]+$/.test(stringValue)) {
|
|
@@ -419,7 +423,6 @@ function ModeTabs({rootMode, compact = false}) {
|
|
|
419
423
|
return html`
|
|
420
424
|
<${Box} marginBottom=${compact ? 0 : 1} flexWrap="wrap">
|
|
421
425
|
${[
|
|
422
|
-
{id: 'collections', label: 'Home (h)'},
|
|
423
426
|
{id: 'areas', label: 'Shelves (w)'},
|
|
424
427
|
{id: 'sources', label: 'Sources (r)'},
|
|
425
428
|
].map((tab) => {
|
|
@@ -860,12 +863,12 @@ function HelpOverlay({viewport = null}) {
|
|
|
860
863
|
subtitle="Keyboard and navigation for the library view."
|
|
861
864
|
footerLines=${['? or Esc closes help']}
|
|
862
865
|
>
|
|
863
|
-
<${Text} color=${COLORS.text}>Arrow keys move between shelves,
|
|
864
|
-
<${Text} color=${COLORS.text}>Enter opens the focused shelf
|
|
866
|
+
<${Text} color=${COLORS.text}>Arrow keys move between shelves, sources, lanes, and picks.<//>
|
|
867
|
+
<${Text} color=${COLORS.text}>Enter opens the focused shelf, source, lane, or pick.<//>
|
|
865
868
|
<${Text} color=${COLORS.text}>/ opens library search, : opens the command palette, ? closes this help.<//>
|
|
866
869
|
<${Text} color=${COLORS.text}>b or Esc goes back, c opens curator actions, i opens install choices, o opens upstream, q quits.<//>
|
|
867
870
|
<${Text} color=${COLORS.text}>t cycles the house themes.<//>
|
|
868
|
-
<${Text} color=${COLORS.muted}>
|
|
871
|
+
<${Text} color=${COLORS.muted}>Shelves are the default library view. Sources stay available when provenance matters more than task-first browsing.<//>
|
|
869
872
|
<//>
|
|
870
873
|
`;
|
|
871
874
|
}
|
|
@@ -880,7 +883,7 @@ function PaletteOverlay({query, setQuery, items, selectedIndex, viewport = null}
|
|
|
880
883
|
<${ModalShell}
|
|
881
884
|
width=${viewport?.micro ? 66 : 86}
|
|
882
885
|
title="Command palette"
|
|
883
|
-
subtitle="Jump
|
|
886
|
+
subtitle="Jump across shelves, sources, and curator actions."
|
|
884
887
|
footerLines=${['Enter runs the command · Esc closes the palette']}
|
|
885
888
|
>
|
|
886
889
|
<${Box} marginTop=${1}>
|
|
@@ -1400,11 +1403,9 @@ function InstallChooser({skill, scope, agent, selectedIndex, columns, viewport =
|
|
|
1400
1403
|
}
|
|
1401
1404
|
|
|
1402
1405
|
function buildBreadcrumbs(rootMode, stack, catalog) {
|
|
1403
|
-
const rootLabel = rootMode === '
|
|
1404
|
-
? '
|
|
1405
|
-
:
|
|
1406
|
-
? 'Shelves'
|
|
1407
|
-
: 'Source Repos';
|
|
1406
|
+
const rootLabel = rootMode === 'areas'
|
|
1407
|
+
? 'Shelves'
|
|
1408
|
+
: 'Sources';
|
|
1408
1409
|
const trail = ['Atlas', rootLabel];
|
|
1409
1410
|
|
|
1410
1411
|
for (const entry of stack.slice(1)) {
|
|
@@ -1468,13 +1469,13 @@ function getCollectionItems(catalog) {
|
|
|
1468
1469
|
}));
|
|
1469
1470
|
}
|
|
1470
1471
|
|
|
1471
|
-
function
|
|
1472
|
+
function getShelfItems(catalog) {
|
|
1472
1473
|
return catalog.areas
|
|
1473
1474
|
.filter((area) => area.skillCount > 0)
|
|
1474
1475
|
.map((area) => ({
|
|
1475
1476
|
id: area.id,
|
|
1476
1477
|
title: area.title,
|
|
1477
|
-
count:
|
|
1478
|
+
count: formatCount(area.skillCount, 'skill'),
|
|
1478
1479
|
description: area.description,
|
|
1479
1480
|
chips: area.branches.slice(0, 2).map((branch) => branch.title),
|
|
1480
1481
|
sampleLines: [
|
|
@@ -1484,8 +1485,8 @@ function getHomeItems(catalog) {
|
|
|
1484
1485
|
.map((skill) => skill.title)
|
|
1485
1486
|
.join(', ')}`,
|
|
1486
1487
|
],
|
|
1487
|
-
footerLeft: `${area.repoCount}
|
|
1488
|
-
footerRight: '
|
|
1488
|
+
footerLeft: `${formatCount(area.repoCount, 'repo')} · ${formatCount(area.branches.length, 'lane')}`,
|
|
1489
|
+
footerRight: 'Open',
|
|
1489
1490
|
}));
|
|
1490
1491
|
}
|
|
1491
1492
|
|
|
@@ -1534,12 +1535,12 @@ function getSourceItems(catalog) {
|
|
|
1534
1535
|
return catalog.sources.map((source) => ({
|
|
1535
1536
|
id: source.slug,
|
|
1536
1537
|
title: source.title,
|
|
1537
|
-
count:
|
|
1538
|
+
count: formatCount(source.skillCount, 'skill'),
|
|
1538
1539
|
description: sourceNoteFor(source.slug, source.slug),
|
|
1539
1540
|
chips: source.branches.slice(0, 2).map((branch) => `${branch.areaTitle} / ${branch.title}`),
|
|
1540
|
-
sampleLines: source.skills.slice(0, 2).map((skill) => skill.title),
|
|
1541
|
-
footerLeft: `${source.areaCount}
|
|
1542
|
-
footerRight: '
|
|
1541
|
+
sampleLines: source.skills.slice(0, 2).map((skill) => `${skill.title} · ${skill.workAreaTitle}`),
|
|
1542
|
+
footerLeft: `${formatCount(source.areaCount, 'shelf', 'shelves')} · ${formatCount(source.branchCount, 'lane')}`,
|
|
1543
|
+
footerRight: 'Open',
|
|
1543
1544
|
}));
|
|
1544
1545
|
}
|
|
1545
1546
|
|
|
@@ -1547,12 +1548,14 @@ function getAreaItems(area) {
|
|
|
1547
1548
|
return area.branches.map((branch) => ({
|
|
1548
1549
|
id: branch.id,
|
|
1549
1550
|
title: branch.title,
|
|
1550
|
-
count:
|
|
1551
|
-
description:
|
|
1551
|
+
count: formatCount(branch.skillCount, 'pick'),
|
|
1552
|
+
description: branch.skillCount === 1
|
|
1553
|
+
? (branch.skills[0]?.whyHere || branch.skills[0]?.description || `A focused ${area.title.toLowerCase()} lane.`)
|
|
1554
|
+
: `${branch.title} is one thread inside ${area.title.toLowerCase()}, shaped by ${branch.repoTitles.join(', ')}.`,
|
|
1552
1555
|
chips: branch.repoTitles.slice(0, 2),
|
|
1553
1556
|
sampleLines: branch.skills.slice(0, 2).map((skill) => `${skill.title} · ${skill.sourceTitle}`),
|
|
1554
|
-
footerLeft:
|
|
1555
|
-
footerRight: '
|
|
1557
|
+
footerLeft: formatCount(branch.repoCount, 'publisher'),
|
|
1558
|
+
footerRight: 'Open',
|
|
1556
1559
|
}));
|
|
1557
1560
|
}
|
|
1558
1561
|
|
|
@@ -1560,11 +1563,13 @@ function getSourceBranchItems(source) {
|
|
|
1560
1563
|
return source.branches.map((branch) => ({
|
|
1561
1564
|
id: branch.id,
|
|
1562
1565
|
title: `${branch.areaTitle} / ${branch.title}`,
|
|
1563
|
-
count:
|
|
1564
|
-
description:
|
|
1566
|
+
count: formatCount(branch.skillCount, 'pick'),
|
|
1567
|
+
description: branch.skillCount === 1
|
|
1568
|
+
? (branch.skills[0]?.whyHere || branch.skills[0]?.description || `${source.title} contributes this lane into the library.`)
|
|
1569
|
+
: `${source.title} feeds this lane into ${branch.areaTitle}.`,
|
|
1565
1570
|
sampleLines: branch.skills.slice(0, 2).map((skill) => skill.title),
|
|
1566
|
-
footerLeft: `${branch.skillCount}
|
|
1567
|
-
footerRight: '
|
|
1571
|
+
footerLeft: `${branch.areaTitle} · ${formatCount(branch.skillCount, 'pick')}`,
|
|
1572
|
+
footerRight: 'Open',
|
|
1568
1573
|
}));
|
|
1569
1574
|
}
|
|
1570
1575
|
|
|
@@ -1576,7 +1581,7 @@ function getSkillItems(skills) {
|
|
|
1576
1581
|
description: skill.whyHere || skill.description,
|
|
1577
1582
|
chips: [skill.sourceTitle, skill.syncMode],
|
|
1578
1583
|
footerLeft: `${skill.workAreaTitle} / ${skill.branchTitle}`,
|
|
1579
|
-
footerRight: '
|
|
1584
|
+
footerRight: 'Inspect',
|
|
1580
1585
|
}));
|
|
1581
1586
|
}
|
|
1582
1587
|
|
|
@@ -1588,7 +1593,7 @@ function getCollectionSkillItems(collection) {
|
|
|
1588
1593
|
description: skill.whyHere || skill.description,
|
|
1589
1594
|
chips: [skill.workAreaTitle, skill.sourceTitle],
|
|
1590
1595
|
footerLeft: `${skill.branchTitle} · ${skill.syncMode}`,
|
|
1591
|
-
footerRight: '
|
|
1596
|
+
footerRight: 'Inspect',
|
|
1592
1597
|
}));
|
|
1593
1598
|
}
|
|
1594
1599
|
|
|
@@ -1666,11 +1671,9 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
1666
1671
|
const [bootReady, setBootReady] = useState(false);
|
|
1667
1672
|
const [catalog, setCatalog] = useState(initialCatalog);
|
|
1668
1673
|
|
|
1669
|
-
const [rootMode, setRootMode] = useState('
|
|
1674
|
+
const [rootMode, setRootMode] = useState('areas');
|
|
1670
1675
|
const [stack, setStack] = useState([{type: 'home'}]);
|
|
1671
1676
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
1672
|
-
const [homeSectionIndex, setHomeSectionIndex] = useState(0);
|
|
1673
|
-
const [homeSelections, setHomeSelections] = useState({});
|
|
1674
1677
|
const [searchMode, setSearchMode] = useState(false);
|
|
1675
1678
|
const [helpOpen, setHelpOpen] = useState(false);
|
|
1676
1679
|
const [paletteOpen, setPaletteOpen] = useState(false);
|
|
@@ -1868,52 +1871,6 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
1868
1871
|
|
|
1869
1872
|
const breadcrumbs = buildBreadcrumbs(rootMode, stack, catalog);
|
|
1870
1873
|
const currentSkillsSpec = currentSkill && agent ? getSkillsInstallSpec(currentSkill, agent) : null;
|
|
1871
|
-
const curatedHomeSections = useMemo(() => {
|
|
1872
|
-
const myPicks = catalog.collections.find((collection) => collection.id === 'my-picks');
|
|
1873
|
-
|
|
1874
|
-
return [
|
|
1875
|
-
{
|
|
1876
|
-
id: 'shelves',
|
|
1877
|
-
title: 'Shelves',
|
|
1878
|
-
subtitle: 'Start from the work itself. Each shelf stays small enough to scan in one pass.',
|
|
1879
|
-
kind: 'area',
|
|
1880
|
-
mode: 'default',
|
|
1881
|
-
items: getHomeItems(catalog),
|
|
1882
|
-
},
|
|
1883
|
-
{
|
|
1884
|
-
id: 'my-picks',
|
|
1885
|
-
title: 'My Picks',
|
|
1886
|
-
subtitle: 'The first stack I would install on a fresh machine.',
|
|
1887
|
-
kind: 'skill',
|
|
1888
|
-
mode: 'skills',
|
|
1889
|
-
items: getSkillItems((myPicks?.skills || []).slice(0, 6)),
|
|
1890
|
-
},
|
|
1891
|
-
{
|
|
1892
|
-
id: 'house',
|
|
1893
|
-
title: 'House Copies',
|
|
1894
|
-
subtitle: 'Bundled, local, and owned here when speed and permanence matter.',
|
|
1895
|
-
kind: 'skill',
|
|
1896
|
-
mode: 'skills',
|
|
1897
|
-
items: getTierSkillItems(catalog, 'house'),
|
|
1898
|
-
},
|
|
1899
|
-
{
|
|
1900
|
-
id: 'upstream',
|
|
1901
|
-
title: 'Cataloged Upstream',
|
|
1902
|
-
subtitle: 'Picked from trusted publishers, but kept live at the source.',
|
|
1903
|
-
kind: 'skill',
|
|
1904
|
-
mode: 'skills',
|
|
1905
|
-
items: getTierSkillItems(catalog, 'upstream'),
|
|
1906
|
-
},
|
|
1907
|
-
{
|
|
1908
|
-
id: 'sources',
|
|
1909
|
-
title: 'Source Repos',
|
|
1910
|
-
subtitle: 'Browse the publishers behind the shelves when provenance matters more than task-first browsing.',
|
|
1911
|
-
kind: 'source',
|
|
1912
|
-
mode: 'default',
|
|
1913
|
-
items: getSourceItems(catalog).slice(0, 6),
|
|
1914
|
-
},
|
|
1915
|
-
].filter((section) => section.items.length > 0);
|
|
1916
|
-
}, [catalog]);
|
|
1917
1874
|
|
|
1918
1875
|
const installOptions = currentSkill
|
|
1919
1876
|
? agent
|
|
@@ -1966,19 +1923,13 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
1966
1923
|
const paletteItems = useMemo(() => {
|
|
1967
1924
|
const items = [];
|
|
1968
1925
|
|
|
1969
|
-
items.push({id: 'go-home', label: 'Home', detail: 'Jump to the curated library home', run: () => {
|
|
1970
|
-
setRootMode('collections');
|
|
1971
|
-
setStack([{type: 'home'}]);
|
|
1972
|
-
setSelectedIndex(0);
|
|
1973
|
-
setPreviewMode(false);
|
|
1974
|
-
}});
|
|
1975
1926
|
items.push({id: 'go-areas', label: 'Shelves', detail: 'Jump to the work-area shelf view', run: () => {
|
|
1976
1927
|
setRootMode('areas');
|
|
1977
1928
|
setStack([{type: 'home'}]);
|
|
1978
1929
|
setSelectedIndex(0);
|
|
1979
1930
|
setPreviewMode(false);
|
|
1980
1931
|
}});
|
|
1981
|
-
items.push({id: 'go-sources', label: '
|
|
1932
|
+
items.push({id: 'go-sources', label: 'Sources', detail: 'Jump to source provenance view', run: () => {
|
|
1982
1933
|
setRootMode('sources');
|
|
1983
1934
|
setStack([{type: 'home'}]);
|
|
1984
1935
|
setSelectedIndex(0);
|
|
@@ -1999,15 +1950,6 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
1999
1950
|
setThemeIndex((value) => (value + 1) % THEMES.length);
|
|
2000
1951
|
}});
|
|
2001
1952
|
|
|
2002
|
-
if (rootMode === 'collections' && current.type === 'home') {
|
|
2003
|
-
items.push({id: 'go-shelves', label: 'Browse by Shelf', detail: 'Jump to the shelf section on the home screen', run: () => {
|
|
2004
|
-
setHomeSectionIndex(0);
|
|
2005
|
-
}});
|
|
2006
|
-
items.push({id: 'go-my-picks', label: 'My Picks', detail: 'Jump to the personal starter stack', run: () => {
|
|
2007
|
-
setHomeSectionIndex(1);
|
|
2008
|
-
}});
|
|
2009
|
-
}
|
|
2010
|
-
|
|
2011
1953
|
if (stack.length > 1) {
|
|
2012
1954
|
items.push({id: 'back', label: 'Back', detail: 'Move one level up in the atlas', run: () => {
|
|
2013
1955
|
setStack((currentStack) => currentStack.slice(0, -1));
|
|
@@ -2050,38 +1992,6 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
2050
1992
|
setPaletteIndex(0);
|
|
2051
1993
|
};
|
|
2052
1994
|
|
|
2053
|
-
const setHomeSelection = (sectionIndex, nextIndex) => {
|
|
2054
|
-
setHomeSelections((currentSelections) => ({
|
|
2055
|
-
...currentSelections,
|
|
2056
|
-
[sectionIndex]: nextIndex,
|
|
2057
|
-
}));
|
|
2058
|
-
};
|
|
2059
|
-
|
|
2060
|
-
const openHomeItem = (section, itemIndex) => {
|
|
2061
|
-
const item = section?.items?.[itemIndex];
|
|
2062
|
-
if (!item) return;
|
|
2063
|
-
|
|
2064
|
-
if (section.kind === 'skill') {
|
|
2065
|
-
setStack((currentStack) => [...currentStack, {type: 'skill', skillName: item.id}]);
|
|
2066
|
-
setPreviewMode(false);
|
|
2067
|
-
return;
|
|
2068
|
-
}
|
|
2069
|
-
|
|
2070
|
-
if (section.kind === 'collection') {
|
|
2071
|
-
setStack((currentStack) => [...currentStack, {type: 'collection', collectionId: item.id}]);
|
|
2072
|
-
return;
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
if (section.kind === 'area') {
|
|
2076
|
-
setStack((currentStack) => [...currentStack, {type: 'area', areaId: item.id}]);
|
|
2077
|
-
return;
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
if (section.kind === 'source') {
|
|
2081
|
-
setStack((currentStack) => [...currentStack, {type: 'source', sourceSlug: item.id}]);
|
|
2082
|
-
}
|
|
2083
|
-
};
|
|
2084
|
-
|
|
2085
1995
|
useInput((input, key) => {
|
|
2086
1996
|
if (helpOpen) {
|
|
2087
1997
|
if (input === 'q' || input === '?' || key.escape) {
|
|
@@ -2489,12 +2399,6 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
2489
2399
|
}
|
|
2490
2400
|
|
|
2491
2401
|
if (current.type === 'home') {
|
|
2492
|
-
if (input === 'h' || input === 'c') {
|
|
2493
|
-
setRootMode('collections');
|
|
2494
|
-
setSelectedIndex(0);
|
|
2495
|
-
setHomeSectionIndex(0);
|
|
2496
|
-
return;
|
|
2497
|
-
}
|
|
2498
2402
|
if (input === 'w') {
|
|
2499
2403
|
setRootMode('areas');
|
|
2500
2404
|
setSelectedIndex(0);
|
|
@@ -2506,39 +2410,6 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
2506
2410
|
return;
|
|
2507
2411
|
}
|
|
2508
2412
|
|
|
2509
|
-
if (rootMode === 'collections') {
|
|
2510
|
-
const sectionCount = curatedHomeSections.length;
|
|
2511
|
-
const currentSection = curatedHomeSections[homeSectionIndex];
|
|
2512
|
-
const currentItemCount = currentSection?.items?.length || 0;
|
|
2513
|
-
const currentHomeIndex = homeSelections[homeSectionIndex] || 0;
|
|
2514
|
-
|
|
2515
|
-
if (key.upArrow || input === 'k') {
|
|
2516
|
-
setHomeSectionIndex((value) => clamp(value - 1, 0, Math.max(0, sectionCount - 1)));
|
|
2517
|
-
return;
|
|
2518
|
-
}
|
|
2519
|
-
|
|
2520
|
-
if (key.downArrow || input === 'j') {
|
|
2521
|
-
setHomeSectionIndex((value) => clamp(value + 1, 0, Math.max(0, sectionCount - 1)));
|
|
2522
|
-
return;
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
if (key.leftArrow || input === 'h') {
|
|
2526
|
-
setHomeSelection(homeSectionIndex, clamp(currentHomeIndex - 1, 0, Math.max(0, currentItemCount - 1)));
|
|
2527
|
-
return;
|
|
2528
|
-
}
|
|
2529
|
-
|
|
2530
|
-
if (key.rightArrow || input === 'l') {
|
|
2531
|
-
setHomeSelection(homeSectionIndex, clamp(currentHomeIndex + 1, 0, Math.max(0, currentItemCount - 1)));
|
|
2532
|
-
return;
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
if (key.return) {
|
|
2536
|
-
openHomeItem(currentSection, currentHomeIndex);
|
|
2537
|
-
setSelectedIndex(0);
|
|
2538
|
-
}
|
|
2539
|
-
return;
|
|
2540
|
-
}
|
|
2541
|
-
|
|
2542
2413
|
const itemCount = rootMode === 'areas' ? catalog.areas.length : catalog.sources.length;
|
|
2543
2414
|
const columnsPerRow = getColumnsPerRow(columns);
|
|
2544
2415
|
|
|
@@ -2664,7 +2535,7 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
2664
2535
|
breadcrumbs=${breadcrumbs}
|
|
2665
2536
|
title="Search the library"
|
|
2666
2537
|
subtitle="Find skills by work area, branch, source repo, or title."
|
|
2667
|
-
metaItems=${[`${catalog.total} skills`, `${catalog.
|
|
2538
|
+
metaItems=${[`${catalog.total} skills`, `${catalog.areas.length} shelves`, `${catalog.sources.length} sources`, activeTheme.label]}
|
|
2668
2539
|
hint="Enter opens a skill · Esc closes search"
|
|
2669
2540
|
viewport=${viewport}
|
|
2670
2541
|
/>
|
|
@@ -2679,110 +2550,45 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
2679
2550
|
<//>
|
|
2680
2551
|
`;
|
|
2681
2552
|
} else if (current.type === 'home') {
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
<${
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
: 'House copies install fast. Cataloged upstream stays live with the publisher. Start with shelves when you want taste, not search results.'}
|
|
2722
|
-
<//>
|
|
2723
|
-
<${Box} marginTop=${1} flexDirection="column">
|
|
2724
|
-
${supportingSectionIndices.map((index) => {
|
|
2725
|
-
const section = curatedHomeSections[index];
|
|
2726
|
-
const sectionItemIndex = homeSelections[index] || 0;
|
|
2727
|
-
const sectionItem = section.items[sectionItemIndex] || section.items[0];
|
|
2728
|
-
return html`
|
|
2729
|
-
<${Box} key=${section.id} flexDirection="column" marginBottom=${1}>
|
|
2730
|
-
<${CompactShelfPreview}
|
|
2731
|
-
title=${section.title}
|
|
2732
|
-
subtitle=${section.subtitle}
|
|
2733
|
-
active=${false}
|
|
2734
|
-
summary=${sectionItem
|
|
2735
|
-
? `${section.items.length} items · focus: ${sectionItem.title}${sectionItem.description ? ` · ${compactText(sectionItem.description, viewport.micro ? 36 : 64)}` : ''}`
|
|
2736
|
-
: `${section.items.length} items`}
|
|
2737
|
-
compact=${viewport.compact}
|
|
2738
|
-
/>
|
|
2739
|
-
<//>
|
|
2740
|
-
`;
|
|
2741
|
-
})}
|
|
2742
|
-
<//>
|
|
2743
|
-
<//>
|
|
2744
|
-
`;
|
|
2745
|
-
} else {
|
|
2746
|
-
const homeItems = rootMode === 'areas' ? getHomeItems(catalog) : getSourceItems(catalog);
|
|
2747
|
-
const selectedHomeItem = homeItems[selectedIndex] || homeItems[0];
|
|
2748
|
-
const showHomeInspector = !viewport.compact && Boolean(selectedHomeItem);
|
|
2749
|
-
body = html`
|
|
2750
|
-
<${Box} flexDirection="column">
|
|
2751
|
-
<${Header}
|
|
2752
|
-
breadcrumbs=${breadcrumbs}
|
|
2753
|
-
title=${rootMode === 'areas' ? 'Browse the shelves' : 'Browse the publishers'}
|
|
2754
|
-
subtitle=${rootMode === 'areas'
|
|
2755
|
-
? 'Start with the kind of work, then drill into the small set of skills on that shelf.'
|
|
2756
|
-
: 'Browse trusted source repos and the lanes they feed into the shelves.'}
|
|
2757
|
-
metaItems=${[`${catalog.total} skills`, `${catalog.areas.length} shelves`, `${catalog.sources.length} publishers`, `scope ${agent ? agent : (scope || 'global')}`, activeTheme.label]}
|
|
2758
|
-
hint="Arrow keys move · Enter drills in · / searches · : command palette"
|
|
2759
|
-
viewport=${viewport}
|
|
2760
|
-
/>
|
|
2761
|
-
<${ModeTabs} rootMode=${rootMode} compact=${viewport.compact} />
|
|
2762
|
-
<${AtlasGrid}
|
|
2763
|
-
items=${homeItems}
|
|
2764
|
-
selectedIndex=${selectedIndex}
|
|
2765
|
-
columns=${columns}
|
|
2766
|
-
rows=${rows}
|
|
2767
|
-
reservedRows=${getReservedRows('home-grid', viewport, {showInspector: showHomeInspector})}
|
|
2768
|
-
compact=${viewport.compact}
|
|
2769
|
-
/>
|
|
2770
|
-
${showHomeInspector
|
|
2771
|
-
? html`
|
|
2772
|
-
<${Inspector}
|
|
2773
|
-
title=${selectedHomeItem.title}
|
|
2774
|
-
eyebrow=${rootMode === 'areas' ? 'Work area' : 'Source repo'}
|
|
2775
|
-
lines=${[
|
|
2776
|
-
selectedHomeItem.description,
|
|
2777
|
-
...(selectedHomeItem.sampleLines || []),
|
|
2778
|
-
]}
|
|
2779
|
-
footer="Enter opens the focused tile"
|
|
2780
|
-
/>
|
|
2781
|
-
`
|
|
2782
|
-
: null}
|
|
2783
|
-
<//>
|
|
2784
|
-
`;
|
|
2785
|
-
}
|
|
2553
|
+
const homeItems = rootMode === 'areas' ? getShelfItems(catalog) : getSourceItems(catalog);
|
|
2554
|
+
const selectedHomeItem = homeItems[selectedIndex] || homeItems[0];
|
|
2555
|
+
const showHomeInspector = !viewport.compact && Boolean(selectedHomeItem);
|
|
2556
|
+
body = html`
|
|
2557
|
+
<${Box} flexDirection="column">
|
|
2558
|
+
<${Header}
|
|
2559
|
+
breadcrumbs=${breadcrumbs}
|
|
2560
|
+
title=${rootMode === 'areas' ? LIBRARY_THESIS : 'Trusted publishers'}
|
|
2561
|
+
subtitle=${rootMode === 'areas'
|
|
2562
|
+
? 'Start with the work. Each shelf stays small enough to scan and opinionated enough to trust.'
|
|
2563
|
+
: 'See where the picks come from and which lanes each publisher feeds into the library.'}
|
|
2564
|
+
metaItems=${[`${catalog.total} skills`, `${catalog.areas.length} shelves`, `${catalog.sources.length} sources`, `scope ${agent ? agent : (scope || 'global')}`, activeTheme.label]}
|
|
2565
|
+
hint="Arrow keys move · Enter drills in · / searches · : command palette"
|
|
2566
|
+
viewport=${viewport}
|
|
2567
|
+
/>
|
|
2568
|
+
<${ModeTabs} rootMode=${rootMode} compact=${viewport.compact} />
|
|
2569
|
+
<${AtlasGrid}
|
|
2570
|
+
items=${homeItems}
|
|
2571
|
+
selectedIndex=${selectedIndex}
|
|
2572
|
+
columns=${columns}
|
|
2573
|
+
rows=${rows}
|
|
2574
|
+
reservedRows=${getReservedRows('home-grid', viewport, {showInspector: showHomeInspector})}
|
|
2575
|
+
compact=${viewport.compact}
|
|
2576
|
+
/>
|
|
2577
|
+
${showHomeInspector
|
|
2578
|
+
? html`
|
|
2579
|
+
<${Inspector}
|
|
2580
|
+
title=${selectedHomeItem.title}
|
|
2581
|
+
eyebrow=${rootMode === 'areas' ? 'Shelf' : 'Source'}
|
|
2582
|
+
lines=${[
|
|
2583
|
+
selectedHomeItem.description,
|
|
2584
|
+
...(selectedHomeItem.sampleLines || []),
|
|
2585
|
+
]}
|
|
2586
|
+
footer="Enter opens the focused tile"
|
|
2587
|
+
/>
|
|
2588
|
+
`
|
|
2589
|
+
: null}
|
|
2590
|
+
<//>
|
|
2591
|
+
`;
|
|
2786
2592
|
} else if (current.type === 'collection' && currentCollection) {
|
|
2787
2593
|
const selectedSkill = currentCollection.skills[selectedIndex] || currentCollection.skills[0];
|
|
2788
2594
|
const startHereSkills = currentCollection.skills.slice(0, 3);
|
|
@@ -3028,11 +2834,11 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
|
|
|
3028
2834
|
: 'Enter open · b back · : commands · q quit'
|
|
3029
2835
|
: current.type === 'skill'
|
|
3030
2836
|
? '/ search · : palette · b back · c curate · i install · p preview · o upstream · t theme · ? help · q quit'
|
|
3031
|
-
: '/ search · : palette · Enter open · b back ·
|
|
2837
|
+
: '/ search · : palette · Enter open · b back · w/r switch views · t theme · ? help · q quit';
|
|
3032
2838
|
const footerMode = current.type === 'skill'
|
|
3033
2839
|
? 'DETAIL'
|
|
3034
2840
|
: current.type === 'home'
|
|
3035
|
-
? rootMode
|
|
2841
|
+
? rootMode === 'areas' ? 'SHELVES' : 'SOURCES'
|
|
3036
2842
|
: current.type.toUpperCase();
|
|
3037
2843
|
const footerDetail = currentSkill
|
|
3038
2844
|
? `${currentSkill.title} · ${activeTheme.label}`
|